CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
RunManagerMTWorker.cc
Go to the documentation of this file.
13 
20 
26 
32 
37 
39 
41 
43 
44 #include "G4Event.hh"
45 #include "G4Run.hh"
46 #include "G4SystemOfUnits.hh"
47 #include "G4Threading.hh"
48 #include "G4UImanager.hh"
49 #include "G4WorkerThread.hh"
50 #include "G4WorkerRunManagerKernel.hh"
51 #include "G4StateManager.hh"
52 #include "G4TransportationManager.hh"
53 
54 #include <atomic>
55 #include <thread>
56 #include <sstream>
57 
58 
59 // from https://hypernews.cern.ch/HyperNews/CMS/get/edmFramework/3302/2.html
60 namespace {
61  static std::atomic<int> thread_counter{ 0 };
62 
63  int get_new_thread_index() {
64  return thread_counter++;
65  }
66 
67  static thread_local int s_thread_index = get_new_thread_index();
68 
69  int getThreadIndex() { return s_thread_index; }
70 
71  void createWatchers(const edm::ParameterSet& iP,
72  SimActivityRegistry& iReg,
73  std::vector<std::shared_ptr<SimWatcher> >& oWatchers,
74  std::vector<std::shared_ptr<SimProducer> >& oProds,
75  int thisThreadID
76  )
77  {
78  using namespace std;
79  using namespace edm;
80  if(!iP.exists("Watchers"))
81  return;
82 
83  vector<ParameterSet> watchers = iP.getParameter<vector<ParameterSet> >("Watchers");
84 
85  if(!watchers.empty() && thisThreadID > 0) {
86  throw cms::Exception("Unsupported") << "SimWatchers are not supported for more than 1 thread. If this use case is needed, RunManagerMTWorker has to be updated, and SimWatchers and SimProducers have to be made thread safe.";
87  }
88 
89  for(vector<ParameterSet>::iterator itWatcher = watchers.begin();
90  itWatcher != watchers.end();
91  ++itWatcher) {
92  std::unique_ptr<SimWatcherMakerBase> maker(
93  SimWatcherFactory::get()->create(itWatcher->getParameter<std::string>("type"))
94  );
95  if(maker.get()==0) {
96  throw SimG4Exception("Unable to find the requested Watcher");
97  }
98 
99  std::shared_ptr<SimWatcher> watcherTemp;
100  std::shared_ptr<SimProducer> producerTemp;
101  maker->make(*itWatcher,iReg,watcherTemp,producerTemp);
102  oWatchers.push_back(watcherTemp);
103  if(producerTemp) {
104  oProds.push_back(producerTemp);
105  }
106  }
107  }
108 }
109 
111  std::unique_ptr<CustomUIsession> UIsession;
112  std::unique_ptr<RunAction> userRunAction;
113  std::unique_ptr<SimRunInterface> runInterface;
115  std::unique_ptr<SimTrackManager> trackManager;
116  std::vector<SensitiveTkDetector*> sensTkDets;
117  std::vector<SensitiveCaloDetector*> sensCaloDets;
118  std::vector<std::shared_ptr<SimWatcher> > watchers;
119  std::vector<std::shared_ptr<SimProducer> > producers;
120  std::unique_ptr<sim::FieldBuilder> fieldBuilder;
121  std::unique_ptr<G4Run> currentRun;
122  std::unique_ptr<G4Event> currentEvent;
124  bool threadInitialized = false;
125  bool runTerminated = false;
126 };
127 
129 
131  m_generator(iConfig.getParameter<edm::ParameterSet>("Generator")),
132  m_InToken(iC.consumes<edm::HepMCProduct>(iConfig.getParameter<edm::ParameterSet>("Generator").getParameter<std::string>("HepMCProductLabel"))),
133  m_theLHCTlinkToken(iC.consumes<edm::LHCTransportLinkContainer>(iConfig.getParameter<edm::InputTag>("theLHCTlinkTag"))),
134  m_nonBeam(iConfig.getParameter<bool>("NonBeamEvent")),
135  m_pUseMagneticField(iConfig.getParameter<bool>("UseMagneticField")),
136  m_EvtMgrVerbosity(iConfig.getUntrackedParameter<int>("G4EventManagerVerbosity",0)),
137  m_pField(iConfig.getParameter<edm::ParameterSet>("MagneticField")),
138  m_pRunAction(iConfig.getParameter<edm::ParameterSet>("RunAction")),
139  m_pEventAction(iConfig.getParameter<edm::ParameterSet>("EventAction")),
140  m_pStackingAction(iConfig.getParameter<edm::ParameterSet>("StackingAction")),
141  m_pTrackingAction(iConfig.getParameter<edm::ParameterSet>("TrackingAction")),
142  m_pSteppingAction(iConfig.getParameter<edm::ParameterSet>("SteppingAction")),
143  m_pCustomUIsession(iConfig.getUntrackedParameter<edm::ParameterSet>("CustomUIsession")),
144  m_p(iConfig)
145 {
146  initializeTLS();
147 }
148 
150  if(!(m_tls && m_tls->runTerminated)) { terminateRun(); }
151  // RunManagerMT has 'delete m_runInterface' in the destructor, but
152  // doesn't make much sense here because it is thread_local and we're
153  // not guaranteed to run the destructor on each of the threads.
154 }
155 
157  terminateRun();
158 }
159 
161  if(m_tls)
162  return;
163  m_tls = new TLSData;
164 
165  edm::Service<SimActivityRegistry> otherRegistry;
166  //Look for an outside SimActivityRegistry
167  // this is used by the visualization code
168  int thisID = getThreadIndex();
169  if(otherRegistry){
170  m_tls->registry.connect(*otherRegistry);
171  if(thisID > 0) {
172  throw cms::Exception("Unsupported") << "SimActivityRegistry service (i.e. visualization) is not supported for more than 1 thread. If this use case is needed, RunManagerMTWorker has to be updated.";
173  }
174  }
175 
177 }
178 
179 void RunManagerMTWorker::initializeThread(const RunManagerMT& runManagerMaster, const edm::EventSetup& es) {
180  // I guess everything initialized here should be in thread_local storage
181  initializeTLS();
182 
183  int thisID = getThreadIndex();
184 
185  // Initialize per-thread output
186  G4Threading::G4SetThreadId( thisID );
187  G4UImanager::GetUIpointer()->SetUpForAThread( thisID );
189  if(uitype == "MessageLogger") {
190  m_tls->UIsession.reset(new CustomUIsession());
191  }
192  else if(uitype == "MessageLoggerThreadPrefix") {
194  }
195  else if(uitype == "FilePerThread") {
197  }
198  else {
199  throw cms::Exception("Configuration") << "Invalid value of CustomUIsession.Type '" << uitype << "', valid are MessageLogger, MessageLoggerThreadPrefix, FilePerThread";
200  }
201 
202  // Initialize worker part of shared resources (geometry, physics)
203  G4WorkerThread::BuildGeometryAndPhysicsVector();
204 
205  // Create worker run manager
206  G4RunManagerKernel *kernel = G4WorkerRunManagerKernel::GetRunManagerKernel();
207  if(!kernel) kernel = new G4WorkerRunManagerKernel();
208 
209  // Set the geometry for the worker, share from master
211 
212  // we need the track manager now
213  m_tls->trackManager.reset(new SimTrackManager());
214 
215  // Get DDCompactView, or would it be better to get the object from
216  // runManagerMaster instead of EventSetup in here?
218  es.get<IdealGeometryRecord>().get(pDD);
219 
220  // setup the magnetic field
222  {
223  const GlobalPoint g(0.,0.,0.);
224 
226  es.get<IdealMagneticFieldRecord>().get(pMF);
227 
229  G4TransportationManager * tM =
230  G4TransportationManager::GetTransportationManager();
231  m_tls->fieldBuilder->build( tM->GetFieldManager(),
232  tM->GetPropagatorInField(),
233  runManagerMaster.chordFinderSetterForWorker());
234  }
235 
236 
237  // attach sensitive detector
238  AttachSD attach;
239  std::pair< std::vector<SensitiveTkDetector*>,
240  std::vector<SensitiveCaloDetector*> > sensDets =
241  attach.create(runManagerMaster.world(),
242  (*pDD),
243  runManagerMaster.catalog(),
244  m_p,
245  m_tls->trackManager.get(),
246  m_tls->registry);
247 
248  m_tls->sensTkDets.swap(sensDets.first);
249  m_tls->sensCaloDets.swap(sensDets.second);
250 
251  edm::LogInfo("SimG4CoreApplication")
252  << " RunManagerMTWorker: Sensitive Detector "
253  << "building finished; found "
254  << m_tls->sensTkDets.size()
255  << " Tk type Producers, and "
256  << m_tls->sensCaloDets.size()
257  << " Calo type producers ";
258 
259  // Set the physics list for the worker, share from master
260  PhysicsList *physicsList = runManagerMaster.physicsListForWorker();
261 
262  edm::LogInfo("SimG4CoreApplication")
263  << "RunManagerMTWorker: start initialisation of PhysicsList for a thread";
264 
265  physicsList->InitializeWorker();
266  kernel->SetPhysics(physicsList);
267  kernel->InitializePhysics();
268 
269  const bool kernelInit = kernel->RunInitialization();
270  if(!kernelInit)
271  throw SimG4Exception("G4WorkerRunManagerKernel initialization failed");
272 
273  //tell all interesting parties that we are beginning the job
274  BeginOfJob aBeginOfJob(&es);
275  m_tls->registry.beginOfJobSignal_(&aBeginOfJob);
276 
278  /*
279  for(const std::string& command: runManagerMaster.G4Commands()) {
280  edm::LogInfo("SimG4CoreApplication") << "RunManagerMTWorker:: Requests UI: "
281  << command;
282  G4UImanager::GetUIpointer()->ApplyCommand(command);
283  }
284  */
285 }
286 
288  m_tls->runInterface.reset(new SimRunInterface(this, false));
290  m_tls->userRunAction->SetMaster(false);
291  Connect(m_tls->userRunAction.get());
292 
293  G4RunManagerKernel *kernel = G4WorkerRunManagerKernel::GetRunManagerKernel();
294  G4EventManager * eventManager = kernel->GetEventManager();
295  eventManager->SetVerboseLevel(m_EvtMgrVerbosity);
296 
297  EventAction * userEventAction =
299  Connect(userEventAction);
300  eventManager->SetUserAction(userEventAction);
301 
302  TrackingAction* userTrackingAction =
303  new TrackingAction(userEventAction,m_pTrackingAction);
304  Connect(userTrackingAction);
305  eventManager->SetUserAction(userTrackingAction);
306 
307  SteppingAction* userSteppingAction =
308  new SteppingAction(userEventAction,m_pSteppingAction);
309  Connect(userSteppingAction);
310  eventManager->SetUserAction(userSteppingAction);
311 
312  eventManager->SetUserAction(new StackingAction(userTrackingAction,
314 
315 }
316 
318 {
321 }
322 
324 {
327 }
328 
330 {
333 }
334 
336 {
338 }
339 
341  initializeTLS();
342  return m_tls->trackManager.get();
343 }
344 std::vector<SensitiveTkDetector*>& RunManagerMTWorker::sensTkDetectors() {
345  initializeTLS();
346  return m_tls->sensTkDets;
347 }
348 std::vector<SensitiveCaloDetector*>& RunManagerMTWorker::sensCaloDetectors() {
349  initializeTLS();
350  return m_tls->sensCaloDets;
351 }
352 std::vector<std::shared_ptr<SimProducer> > RunManagerMTWorker::producers() {
353  initializeTLS();
354  return m_tls->producers;
355 }
356 
357 
359  m_tls->currentRun.reset(new G4Run());
360  G4StateManager::GetStateManager()->SetNewState(G4State_GeomClosed);
361  if (m_tls->userRunAction) { m_tls->userRunAction->BeginOfRunAction(m_tls->currentRun.get()); }
362 }
363 
365  if(m_tls && m_tls->userRunAction) {
366  m_tls->userRunAction->EndOfRunAction(m_tls->currentRun.get());
367  m_tls->userRunAction.reset();
368  }
369 
370  G4RunManagerKernel *kernel = G4WorkerRunManagerKernel::GetRunManagerKernel();
371  if(kernel && m_tls && !m_tls->runTerminated) {
372  m_tls->currentEvent.reset();
373  m_simEvent.reset();
374  kernel->RunTermination();
375  m_tls->runTerminated = true;
376  }
377 }
378 
379 void RunManagerMTWorker::produce(const edm::Event& inpevt, const edm::EventSetup& es, const RunManagerMT& runManagerMaster) {
380  // The initialization and begin/end run is a bit convoluted due to
381  // - Geant4 deals per-thread
382  // - OscarMTProducer deals per-stream
383  // and framework/TBB is free to schedule work in streams to the
384  // threads as it likes.
385  //
386  // We have to do the per-thread initialization, and per-thread
387  // per-run initialization here by ourselves.
388  if(!(m_tls && m_tls->threadInitialized)) {
389  LogDebug("SimG4CoreApplication") << "RunManagerMTWorker::produce(): stream " << inpevt.streamID() << " thread " << getThreadIndex() << " initializing";
390  initializeThread(runManagerMaster, es);
391  m_tls->threadInitialized = true;
392  }
393  // Initialize run
394  if(inpevt.id().run() != m_tls->currentRunNumber) {
395  if(m_tls->currentRunNumber != 0 && !m_tls->runTerminated) {
396  // If previous run in this thread was not terminated via endRun() call, terminate it now
397  terminateRun();
398  }
399  initializeRun();
400  m_tls->currentRunNumber = inpevt.id().run();
401  }
402  m_tls->runInterface->setRunManagerMTWorker(this); // For UserActions
403 
404 
405  m_tls->currentEvent.reset(generateEvent(inpevt));
406 
407  m_simEvent.reset(new G4SimEvent());
408  m_simEvent->hepEvent(m_generator.genEvent());
410  if (m_generator.genVertex() !=0 ) {
411  auto genVertex = m_generator.genVertex();
412  m_simEvent->collisionPoint(
413  math::XYZTLorentzVectorD(genVertex->x()/centimeter,
414  genVertex->y()/centimeter,
415  genVertex->z()/centimeter,
416  genVertex->t()/second));
417  }
418  if (m_tls->currentEvent->GetNumberOfPrimaryVertex()==0) {
419  edm::LogError("SimG4CoreApplication")
420  << " RunManagerMT::produce event " << inpevt.id().event()
421  << " with no G4PrimaryVertices \n Aborting Run" ;
422 
423  abortRun(false);
424  } else {
425  G4RunManagerKernel *kernel = G4WorkerRunManagerKernel::GetRunManagerKernel();
426  if(!kernel) {
427  std::stringstream ss;
428  ss << "No G4WorkerRunManagerKernel yet for thread index" << getThreadIndex() << ", id " << std::hex << std::this_thread::get_id();
429  throw SimG4Exception(ss.str());
430  }
431  kernel->GetEventManager()->ProcessOneEvent(m_tls->currentEvent.get());
432  }
433 
434  edm::LogInfo("SimG4CoreApplication")
435  << " RunManagerMTWorker: saved : Event " << inpevt.id().event()
436  << " stream id " << inpevt.streamID()
437  << " thread index " << getThreadIndex()
438  << " of weight " << m_simEvent->weight()
439  << " with " << m_simEvent->nTracks() << " tracks and "
440  << m_simEvent->nVertices()
441  << " vertices, generated by " << m_simEvent->nGenParts() << " particles ";
442 }
443 
445  if(m_tls->runTerminated) { return; }
446  G4RunManagerKernel *kernel = G4WorkerRunManagerKernel::GetRunManagerKernel();
447  G4Track* t = kernel->GetEventManager()->GetTrackingManager()->GetTrack();
448  t->SetTrackStatus(fStopAndKill) ;
449 
450  // CMS-specific act
451  //
452  TrackingAction* uta =
453  static_cast<TrackingAction *>(kernel->GetEventManager()->GetUserTrackingAction());
454  uta->PostUserTrackingAction(t) ;
455 
456  m_tls->currentEvent->SetEventAborted();
457 
458  // do NOT call this method for now
459  // because it'll set abortRequested=true (withing G4EventManager)
460  // this will make Geant4, in the event *next* after the aborted one
461  // NOT to get the primary, thus there's NOTHING to trace, and it goes
462  // to the end of G4Event::DoProcessing(G4Event*), where abortRequested
463  // will be reset to true again
464  //
465  //kernel->GetEventManager()->AbortCurrentEvent();
466  //
467  // instead, mimic what it does, except (re)setting abortRequested
468  //
469  kernel->GetEventManager()->GetStackManager()->clear() ;
470  kernel->GetEventManager()->GetTrackingManager()->EventAborted() ;
471 
472  G4StateManager* stateManager = G4StateManager::GetStateManager();
473  stateManager->SetNewState(G4State_GeomClosed);
474 }
475 
476 void RunManagerMTWorker::abortRun(bool softAbort) {
477  if (!softAbort) { abortEvent(); }
478  m_tls->currentRun.reset();
479  terminateRun();
480 }
481 
483  m_tls->currentEvent.reset();
484  m_simEvent.reset();
485 
486  // 64 bits event ID in CMSSW converted into Geant4 event ID
487  G4int evtid = (G4int)inpevt.id().event();
488  G4Event * evt = new G4Event(evtid);
489 
491 
492  inpevt.getByToken(m_InToken, HepMCEvt);
493 
494  m_generator.setGenEvent(HepMCEvt->GetEvent());
495 
496  // required to reset the GenParticle Id for particles transported
497  // along the beam pipe
498  // to their original value for SimTrack creation
499  resetGenParticleId( inpevt );
500 
501  if (!m_nonBeam)
502  {
503  m_generator.HepMC2G4(HepMCEvt->GetEvent(),evt);
504  }
505  else
506  {
507  m_generator.nonBeamEvent2G4(HepMCEvt->GetEvent(),evt);
508  }
509 
510  return evt;
511 }
512 
514 {
516  inpevt.getByToken( m_theLHCTlinkToken, theLHCTlink );
517  if ( theLHCTlink.isValid() ) {
518  m_tls->trackManager->setLHCTransportLink( theLHCTlink.product() );
519  }
520 }
#define LogDebug(id)
RunNumber_t run() const
Definition: EventID.h:39
edm::ParameterSet m_pSteppingAction
T getParameter(std::string const &) const
EventNumber_t event() const
Definition: EventID.h:41
std::vector< std::shared_ptr< SimWatcher > > watchers
const SensitiveDetectorCatalog & catalog() const
Definition: RunManagerMT.h:84
T getUntrackedParameter(std::string const &, T const &) const
virtual const math::XYZTLorentzVector * genVertex() const
Definition: Generator.h:30
std::unique_ptr< G4Event > currentEvent
virtual const double eventWeight() const
Definition: Generator.h:31
ROOT::Math::LorentzVector< ROOT::Math::PxPyPzE4D< double > > XYZTLorentzVectorD
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:14
virtual const HepMC::GenEvent * genEvent() const
Definition: Generator.h:29
SimActivityRegistry::G4StepSignal m_g4StepSignal
SimTrackManager * GetSimTrackManager()
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:462
void connect(Observer< const BeginOfJob * > *iObject)
void HepMC2G4(const HepMC::GenEvent *g, G4Event *e)
Definition: Generator.cc:100
EndOfEventSignal endOfEventSignal_
std::unique_ptr< SimRunInterface > runInterface
SimActivityRegistry::EndOfRunSignal m_endOfRunSignal
Definition: RunAction.h:24
bool exists(std::string const &parameterName) const
checks if a parameter exists
BeginOfRunSignal beginOfRunSignal_
std::vector< SensitiveTkDetector * > sensTkDets
std::unique_ptr< sim::FieldBuilder > fieldBuilder
SimActivityRegistry::EndOfEventSignal m_endOfEventSignal
Definition: EventAction.h:46
static void createWatchers(const edm::ParameterSet &iP, SimActivityRegistry &iReg, std::vector< std::shared_ptr< SimWatcher > > &oWatchers, std::vector< std::shared_ptr< SimProducer > > &oProds)
Definition: RunManager.cc:75
edm::EDGetTokenT< edm::HepMCProduct > m_InToken
const bool m_pUseMagneticField
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e g
Definition: Activities.doc:4
BeginOfJobSignal beginOfJobSignal_
U second(std::pair< T, U > const &p)
edm::ParameterSet m_pEventAction
const DDDWorld & world() const
Definition: RunManagerMT.h:80
std::unique_ptr< SimTrackManager > trackManager
std::unique_ptr< CustomUIsession > UIsession
std::unique_ptr< G4SimEvent > m_simEvent
static thread_local TLSData * m_tls
edm::ParameterSet m_pRunAction
std::vector< SensitiveCaloDetector * > sensCaloDets
std::vector< SensitiveTkDetector * > & sensTkDetectors()
void resetGenParticleId(const edm::Event &inpevt)
std::unique_ptr< RunAction > userRunAction
void setGenEvent(const HepMC::GenEvent *inpevt)
Definition: Generator.h:25
BeginOfEventSignal beginOfEventSignal_
sim::ChordFinderSetter * chordFinderSetterForWorker() const
Definition: RunManagerMT.h:103
SimActivityRegistry::EndOfTrackSignal m_endOfTrackSignal
bool isValid() const
Definition: HandleBase.h:75
EndOfRunSignal endOfRunSignal_
std::vector< std::shared_ptr< SimProducer > > producers
void abortRun(bool softAbort=false)
RunManagerMTWorker(const edm::ParameterSet &iConfig, edm::ConsumesCollector &&i)
void connect(Observer< const T * > *iObs)
does not take ownership of memory
Definition: Signaler.h:59
PhysicsList * physicsListForWorker() const
Definition: RunManagerMT.h:95
T const * product() const
Definition: Handle.h:81
virtual void PostUserTrackingAction(const G4Track *aTrack)
std::vector< SensitiveCaloDetector * > & sensCaloDetectors()
edm::ParameterSet m_pTrackingAction
std::unique_ptr< G4Run > currentRun
edm::ParameterSet m_pField
const T & get() const
Definition: EventSetup.h:56
T const * product() const
Definition: ESHandle.h:86
std::pair< std::vector< SensitiveTkDetector * >, std::vector< SensitiveCaloDetector * > > create(const DDDWorld &w, const DDCompactView &cpv, const SensitiveDetectorCatalog &clg, edm::ParameterSet const &p, const SimTrackManager *m, SimActivityRegistry &reg) const
Definition: AttachSD.cc:23
G4VPhysicalVolume * GetWorldVolumeForWorker() const
Definition: DDDWorld.h:24
G4Event * generateEvent(const edm::Event &inpevt)
edm::EDGetTokenT< edm::LHCTransportLinkContainer > m_theLHCTlinkToken
void nonBeamEvent2G4(const HepMC::GenEvent *g, G4Event *e)
Definition: Generator.cc:500
void initializeThread(const RunManagerMT &runManagerMaster, const edm::EventSetup &es)
static void WorkerSetAsWorld(G4VPhysicalVolume *pv)
Definition: DDDWorld.cc:38
SimActivityRegistry::BeginOfRunSignal m_beginOfRunSignal
Definition: RunAction.h:23
edm::EventID id() const
Definition: EventBase.h:59
edm::ParameterSet m_pCustomUIsession
std::vector< std::shared_ptr< SimProducer > > producers()
StreamID streamID() const
Definition: Event.h:80
std::vector< LHCTransportLink > LHCTransportLinkContainer
unsigned int RunNumber_t
EndOfTrackSignal endOfTrackSignal_
edm::ParameterSet m_p
SimActivityRegistry::BeginOfEventSignal m_beginOfEventSignal
Definition: EventAction.h:45
T get(const Candidate &c)
Definition: component.h:55
BeginOfTrackSignal beginOfTrackSignal_
edm::ParameterSet m_pStackingAction
void Connect(RunAction *)
void produce(const edm::Event &inpevt, const edm::EventSetup &es, const RunManagerMT &runManagerMaster)
SimActivityRegistry::BeginOfTrackSignal m_beginOfTrackSignal