CMS 3D CMS Logo

OscarMTProducer.cc
Go to the documentation of this file.
1 #include <iostream>
2 #include <memory>
3 
9 
14 
20 
26 
29 
31 
36 
38 
39 #include "Randomize.hh"
40 
41 // for some reason void doesn't compile
42 class OscarMTProducer : public edm::stream::EDProducer<edm::GlobalCache<OscarMTMasterThread>, edm::RunCache<int>> {
43 public:
44  typedef std::vector<std::shared_ptr<SimProducer>> Producers;
45 
46  explicit OscarMTProducer(edm::ParameterSet const& p, const OscarMTMasterThread*);
47  ~OscarMTProducer() override;
48 
49  static std::unique_ptr<OscarMTMasterThread> initializeGlobalCache(const edm::ParameterSet& iConfig);
50  static std::shared_ptr<int> globalBeginRun(const edm::Run& iRun,
51  const edm::EventSetup& iSetup,
52  const OscarMTMasterThread* masterThread);
53  static void globalEndRun(const edm::Run& iRun, const edm::EventSetup& iSetup, const RunContext* iContext);
54  static void globalEndJob(OscarMTMasterThread* masterThread);
55 
56  void beginRun(const edm::Run& r, const edm::EventSetup& c) override;
57  void endRun(const edm::Run& r, const edm::EventSetup& c) override;
58  void produce(edm::Event& e, const edm::EventSetup& c) override;
59 
60 private:
62  std::unique_ptr<RunManagerMTWorker> m_runManagerWorker;
65  int m_verbose;
68 };
69 
72 
73 namespace edm {
74  class StreamID;
75 }
76 
77 namespace {
78  //
79  // this machinery allows to set CLHEP static engine
80  // to the one defined by RandomNumberGenerator service
81  // at the beginning of an event, and reset it back to
82  // "default-default" at the end of the event;
83  // Dave D. has decided to implement it this way because
84  // we don't know if there're other modules using CLHEP
85  // static engine, thus we want to ensure that the one
86  // we use for OscarMTProducer is unique to OscarMTProducer
87  //
88  // !!! This not only sets the random engine used by GEANT.
89  // There are a few SimWatchers/SimProducers that generate
90  // random number and also use the global CLHEP random engine
91  // set by this code. If we ever change this design be careful
92  // not to forget about them!!!
93 
94  class StaticRandomEngineSetUnset {
95  public:
96  StaticRandomEngineSetUnset(edm::StreamID const&);
97  explicit StaticRandomEngineSetUnset(CLHEP::HepRandomEngine* engine);
98  ~StaticRandomEngineSetUnset();
99 
100  CLHEP::HepRandomEngine* currentEngine() { return m_currentEngine; }
101 
102  private:
103  CLHEP::HepRandomEngine* m_currentEngine;
104  CLHEP::HepRandomEngine* m_previousEngine;
105  };
106 } // namespace
107 
109  : m_handoff{p.getUntrackedParameter<int>("workerThreadStackSize", 10 * 1024 * 1024)}, m_psetID{p.id()} {
110  m_verbose = p.getParameter<int>("EventVerbose");
111  // Random number generation not allowed here
112  StaticRandomEngineSetUnset random(nullptr);
113 
115  m_handoff.runAndWait([this, &p, token]() {
117  StaticRandomEngineSetUnset random(nullptr);
118  m_runManagerWorker = std::make_unique<RunManagerMTWorker>(p, consumesCollector());
119  });
120  m_masterThread = (nullptr != ms) ? ms : s_masterThread;
121  assert(m_masterThread);
122  m_masterThread->callConsumes(consumesCollector());
123 
124  // declair hit collections
125  produces<edm::SimTrackContainer>().setBranchAlias("SimTracks");
126  produces<edm::SimVertexContainer>().setBranchAlias("SimVertices");
127 
128  auto trackHits = p.getParameter<std::vector<std::string>>("TrackHits");
129  for (auto const& ss : trackHits) {
130  produces<edm::PSimHitContainer>(ss);
131  }
132 
133  auto caloHits = p.getParameter<std::vector<std::string>>("CaloHits");
134  for (auto const& ss : caloHits) {
135  produces<edm::PCaloHitContainer>(ss);
136  }
137 
138  //register any products
139  auto& producers = m_runManagerWorker->producers();
140  for (auto& ptr : producers) {
141  ptr->registerProducts(producesCollector());
142  }
143  edm::LogVerbatim("SimG4CoreApplication")
144  << "OscarMTProducer is constructed with hit collections:" << trackHits.size() << " tracking type; "
145  << caloHits.size() << " calo type; " << producers.size() << " watcher type.";
146 }
147 
150  m_handoff.runAndWait([this, token]() {
152  m_runManagerWorker.reset();
153  });
154 }
155 
156 std::unique_ptr<OscarMTMasterThread> OscarMTProducer::initializeGlobalCache(const edm::ParameterSet& iConfig) {
157  // Random number generation not allowed here
158  StaticRandomEngineSetUnset random(nullptr);
159  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::initializeGlobalCache";
160  if (nullptr == s_masterThread) {
161  auto ret = std::make_unique<OscarMTMasterThread>(iConfig);
162  s_masterThread = ret.get();
163  s_psetID = iConfig.id();
164  return ret;
165  }
166  return {};
167 }
168 
169 std::shared_ptr<int> OscarMTProducer::globalBeginRun(const edm::Run&,
170  const edm::EventSetup& iSetup,
171  const OscarMTMasterThread* masterThread) {
172  // Random number generation not allowed here
173  StaticRandomEngineSetUnset random(nullptr);
174  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::globalBeginRun";
175  if (masterThread) {
176  masterThread->beginRun(iSetup);
177  }
178  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::globalBeginRun done";
179  return std::shared_ptr<int>();
180 }
181 
182 void OscarMTProducer::globalEndRun(const edm::Run&, const edm::EventSetup&, const RunContext* iContext) {
183  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::globalEndRun";
184  if (nullptr != iContext->global()) {
185  iContext->global()->endRun();
186  }
187 }
188 
190  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::globalEndJob";
191  if (masterThread) {
192  masterThread->stopThread();
193  }
194 }
195 
197  if (s_psetID != m_psetID) {
198  throw cms::Exception("DiffOscarMTProducers")
199  << "At least two different OscarMTProducer instances have been"
200  "loaded into the job and they have different configurations.\n"
201  " All OscarMTProducers in a job must have exactly the same configuration.";
202  }
203  int id = m_runManagerWorker->getThreadIndex();
204  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::beginRun threadID=" << id;
206  m_handoff.runAndWait([this, &es, token]() {
208  m_runManagerWorker->beginRun(es);
210  });
211  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::beginRun done threadID=" << id;
212 }
213 
215  StaticRandomEngineSetUnset random(nullptr);
216  int id = m_runManagerWorker->getThreadIndex();
217  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::endRun threadID=" << id;
219  m_handoff.runAndWait([this, token]() {
221  m_runManagerWorker->endRun();
222  });
223  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTProducer::endRun done threadID=" << id;
224 }
225 
227  StaticRandomEngineSetUnset random(e.streamID());
228  auto engine = random.currentEngine();
229  int id = m_runManagerWorker->getThreadIndex();
230  if (0 < m_verbose) {
231  edm::LogVerbatim("SimG4CoreApplication")
232  << "Produce event " << e.id() << " stream " << e.streamID() << " threadID=" << id;
233  //edm::LogVerbatim("SimG4CoreApplication") << " rand= " << G4UniformRand();
234  }
235 
236  auto& sTk = m_runManagerWorker->sensTkDetectors();
237  auto& sCalo = m_runManagerWorker->sensCaloDetectors();
238 
239  TmpSimEvent* evt = nullptr;
241  m_handoff.runAndWait([this, &e, &es, &evt, token, engine]() {
243  StaticRandomEngineSetUnset random(engine);
244  evt = m_runManagerWorker->produce(e, es, m_masterThread->runManagerMaster());
245  });
246 
247  std::unique_ptr<edm::SimTrackContainer> p1(new edm::SimTrackContainer);
248  std::unique_ptr<edm::SimVertexContainer> p2(new edm::SimVertexContainer);
249  evt->load(*p1);
250  evt->load(*p2);
251 
252  if (0 < m_verbose) {
253  edm::LogVerbatim("SimG4CoreApplication") << "Produced " << p2->size() << " SimVertex objects";
254  if (1 < m_verbose) {
255  int nn = p2->size();
256  for (int i = 0; i < nn; ++i) {
257  edm::LogVerbatim("Vertex") << " " << (*p2)[i] << " " << (*p2)[i].processType();
258  }
259  }
260  edm::LogVerbatim("SimG4CoreApplication") << "Produced " << p1->size() << " SimTrack objects";
261  if (1 < m_verbose) {
262  int nn = p1->size();
263  for (int i = 0; i < nn; ++i) {
264  edm::LogVerbatim("Track") << " " << i << ". " << (*p1)[i] << " " << (*p1)[i].crossedBoundary() << " "
265  << (*p1)[i].getIDAtBoundary();
266  }
267  }
268  }
269  e.put(std::move(p1));
270  e.put(std::move(p2));
271 
272  for (auto const& tracker : sTk) {
273  const std::vector<std::string>& v = tracker->getNames();
274  for (auto const& name : v) {
275  std::unique_ptr<edm::PSimHitContainer> product(new edm::PSimHitContainer);
276  tracker->fillHits(*product, name);
277  if (0 < m_verbose && product != nullptr && !product->empty())
278  edm::LogVerbatim("SimG4CoreApplication") << "Produced " << product->size() << " tracker hits <" << name << ">";
279  e.put(std::move(product), name);
280  }
281  }
282  for (auto const& calo : sCalo) {
283  const std::vector<std::string>& v = calo->getNames();
284  for (auto const& name : v) {
285  std::unique_ptr<edm::PCaloHitContainer> product(new edm::PCaloHitContainer);
286  calo->fillHits(*product, name);
287  if (0 < m_verbose && product != nullptr && !product->empty())
288  edm::LogVerbatim("SimG4CoreApplication") << "Produced " << product->size() << " calo hits <" << name << ">";
289  e.put(std::move(product), name);
290  }
291  }
292 
293  auto& producers = m_runManagerWorker->producers();
294  for (auto& prod : producers) {
295  prod.get()->produce(e, es);
296  }
297  if (0 < m_verbose) {
298  edm::LogVerbatim("SimG4CoreApplication")
299  << "Event is produced event " << e.id() << " streamID=" << e.streamID() << " threadID=" << id;
300  //edm::LogWarning("SimG4CoreApplication") << "EventID=" << e.id() << " rand=" << G4UniformRand();
301  }
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
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