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  physicsList->InitializeWorker();
262  kernel->SetPhysics(physicsList);
263  kernel->InitializePhysics();
264 
265  const bool kernelInit = kernel->RunInitialization();
266  if(!kernelInit)
267  throw SimG4Exception("G4WorkerRunManagerKernel initialization failed");
268 
269  //tell all interesting parties that we are beginning the job
270  BeginOfJob aBeginOfJob(&es);
271  m_tls->registry.beginOfJobSignal_(&aBeginOfJob);
272 
274 
275  for(const std::string& command: runManagerMaster.G4Commands()) {
276  edm::LogInfo("SimG4CoreApplication") << "RunManagerMTWorker:: Requests UI: "
277  << command;
278  G4UImanager::GetUIpointer()->ApplyCommand(command);
279  }
280 }
281 
283  m_tls->runInterface.reset(new SimRunInterface(this, false));
284 
286  m_tls->userRunAction->SetMaster(false);
287  Connect(m_tls->userRunAction.get());
288 
289  G4RunManagerKernel *kernel = G4WorkerRunManagerKernel::GetRunManagerKernel();
290  G4EventManager * eventManager = kernel->GetEventManager();
291  eventManager->SetVerboseLevel(m_EvtMgrVerbosity);
292 
293  EventAction * userEventAction =
295  Connect(userEventAction);
296  eventManager->SetUserAction(userEventAction);
297 
298  TrackingAction* userTrackingAction =
299  new TrackingAction(userEventAction,m_pTrackingAction);
300  Connect(userTrackingAction);
301  eventManager->SetUserAction(userTrackingAction);
302 
303  SteppingAction* userSteppingAction =
304  new SteppingAction(userEventAction,m_pSteppingAction);
305  Connect(userSteppingAction);
306  eventManager->SetUserAction(userSteppingAction);
307 
308  eventManager->SetUserAction(new StackingAction(userTrackingAction,
310 
311 }
312 
314 {
317 }
318 
320 {
323 }
324 
326 {
329 }
330 
332 {
334 }
335 
337  initializeTLS();
338  return m_tls->trackManager.get();
339 }
340 std::vector<SensitiveTkDetector*>& RunManagerMTWorker::sensTkDetectors() {
341  initializeTLS();
342  return m_tls->sensTkDets;
343 }
344 std::vector<SensitiveCaloDetector*>& RunManagerMTWorker::sensCaloDetectors() {
345  initializeTLS();
346  return m_tls->sensCaloDets;
347 }
348 std::vector<std::shared_ptr<SimProducer> > RunManagerMTWorker::producers() {
349  initializeTLS();
350  return m_tls->producers;
351 }
352 
353 
355  m_tls->currentRun.reset(new G4Run());
356  G4StateManager::GetStateManager()->SetNewState(G4State_GeomClosed);
357  if (m_tls->userRunAction) { m_tls->userRunAction->BeginOfRunAction(m_tls->currentRun.get()); }
358 }
359 
361  if(m_tls->userRunAction) {
362  m_tls->userRunAction->EndOfRunAction(m_tls->currentRun.get());
363  m_tls->userRunAction.reset();
364  }
365 
366  G4RunManagerKernel *kernel = G4WorkerRunManagerKernel::GetRunManagerKernel();
367  if(!kernel && !m_tls->runTerminated) {
368  m_tls->currentEvent.reset();
369  m_simEvent.reset();
370  kernel->RunTermination();
371  m_tls->runTerminated = true;
372  }
373 }
374 
375 void RunManagerMTWorker::produce(const edm::Event& inpevt, const edm::EventSetup& es, const RunManagerMT& runManagerMaster) {
376  // The initialization and begin/end run is a bit convoluted due to
377  // - Geant4 deals per-thread
378  // - OscarMTProducer deals per-stream
379  // and framework/TBB is free to schedule work in streams to the
380  // threads as it likes.
381  //
382  // We have to do the per-thread initialization, and per-thread
383  // per-run initialization here by ourselves.
384  if(!(m_tls && m_tls->threadInitialized)) {
385  LogDebug("SimG4CoreApplication") << "RunManagerMTWorker::produce(): stream " << inpevt.streamID() << " thread " << getThreadIndex() << " initializing";
386  initializeThread(runManagerMaster, es);
387  m_tls->threadInitialized = true;
388  }
389  // Initialize run
390  if(inpevt.id().run() != m_tls->currentRunNumber) {
391  if(m_tls->currentRunNumber != 0 && !m_tls->runTerminated) {
392  // If previous run in this thread was not terminated via endRun() call, terminate it now
393  terminateRun();
394  }
395  initializeRun();
396  m_tls->currentRunNumber = inpevt.id().run();
397  }
398  m_tls->runInterface->setRunManagerMTWorker(this); // For UserActions
399 
400 
401  m_tls->currentEvent.reset(generateEvent(inpevt));
402 
403  m_simEvent.reset(new G4SimEvent());
404  m_simEvent->hepEvent(m_generator.genEvent());
406  if (m_generator.genVertex() !=0 ) {
407  auto genVertex = m_generator.genVertex();
408  m_simEvent->collisionPoint(
409  math::XYZTLorentzVectorD(genVertex->x()/centimeter,
410  genVertex->y()/centimeter,
411  genVertex->z()/centimeter,
412  genVertex->t()/second));
413  }
414  if (m_tls->currentEvent->GetNumberOfPrimaryVertex()==0) {
415  edm::LogError("SimG4CoreApplication")
416  << " RunManagerMT::produce event " << inpevt.id().event()
417  << " with no G4PrimaryVertices \n Aborting Run" ;
418 
419  abortRun(false);
420  } else {
421  G4RunManagerKernel *kernel = G4WorkerRunManagerKernel::GetRunManagerKernel();
422  if(!kernel) {
423  std::stringstream ss;
424  ss << "No G4WorkerRunManagerKernel yet for thread index" << getThreadIndex() << ", id " << std::hex << std::this_thread::get_id();
425  throw SimG4Exception(ss.str());
426  }
427  kernel->GetEventManager()->ProcessOneEvent(m_tls->currentEvent.get());
428  }
429 
430  edm::LogInfo("SimG4CoreApplication")
431  << " RunManagerMTWorker: saved : Event " << inpevt.id().event()
432  << " stream id " << inpevt.streamID()
433  << " thread index " << getThreadIndex()
434  << " of weight " << m_simEvent->weight()
435  << " with " << m_simEvent->nTracks() << " tracks and "
436  << m_simEvent->nVertices()
437  << " vertices, generated by " << m_simEvent->nGenParts() << " particles ";
438 }
439 
441  if(m_tls->runTerminated) { return; }
442  G4RunManagerKernel *kernel = G4WorkerRunManagerKernel::GetRunManagerKernel();
443  G4Track* t = kernel->GetEventManager()->GetTrackingManager()->GetTrack();
444  t->SetTrackStatus(fStopAndKill) ;
445 
446  // CMS-specific act
447  //
448  TrackingAction* uta =
449  static_cast<TrackingAction *>(kernel->GetEventManager()->GetUserTrackingAction());
450  uta->PostUserTrackingAction(t) ;
451 
452  m_tls->currentEvent->SetEventAborted();
453 
454  // do NOT call this method for now
455  // because it'll set abortRequested=true (withing G4EventManager)
456  // this will make Geant4, in the event *next* after the aborted one
457  // NOT to get the primary, thus there's NOTHING to trace, and it goes
458  // to the end of G4Event::DoProcessing(G4Event*), where abortRequested
459  // will be reset to true again
460  //
461  //kernel->GetEventManager()->AbortCurrentEvent();
462  //
463  // instead, mimic what it does, except (re)setting abortRequested
464  //
465  kernel->GetEventManager()->GetStackManager()->clear() ;
466  kernel->GetEventManager()->GetTrackingManager()->EventAborted() ;
467 
468  G4StateManager* stateManager = G4StateManager::GetStateManager();
469  stateManager->SetNewState(G4State_GeomClosed);
470 }
471 
472 void RunManagerMTWorker::abortRun(bool softAbort) {
473  if (!softAbort) { abortEvent(); }
474  m_tls->currentRun.reset();
475  terminateRun();
476 }
477 
479  m_tls->currentEvent.reset();
480  m_simEvent.reset();
481 
482  // 64 bits event ID in CMSSW converted into Geant4 event ID
483  G4int evtid = (G4int)inpevt.id().event();
484  G4Event * evt = new G4Event(evtid);
485 
487 
488  inpevt.getByToken(m_InToken, HepMCEvt);
489 
490  m_generator.setGenEvent(HepMCEvt->GetEvent());
491 
492  // required to reset the GenParticle Id for particles transported
493  // along the beam pipe
494  // to their original value for SimTrack creation
495  resetGenParticleId( inpevt );
496 
497  if (!m_nonBeam)
498  {
499  m_generator.HepMC2G4(HepMCEvt->GetEvent(),evt);
500  }
501  else
502  {
503  m_generator.nonBeamEvent2G4(HepMCEvt->GetEvent(),evt);
504  }
505 
506  return evt;
507 }
508 
510 {
512  inpevt.getByToken( m_theLHCTlinkToken, theLHCTlink );
513  if ( theLHCTlink.isValid() ) {
514  m_tls->trackManager->setLHCTransportLink( theLHCTlink.product() );
515  }
516 }
#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:81
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:449
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:76
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:77
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:102
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:93
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:55
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:495
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
const std::vector< std::string > & G4Commands() const
Definition: RunManagerMT.h:85
edm::EventID id() const
Definition: EventBase.h:60
edm::ParameterSet m_pCustomUIsession
std::vector< std::shared_ptr< SimProducer > > producers()
StreamID streamID() const
Definition: Event.h:72
std::vector< LHCTransportLink > LHCTransportLinkContainer
unsigned int RunNumber_t
EndOfTrackSignal endOfTrackSignal_
edm::ParameterSet m_p
SurfaceDeformation * create(int type, const std::vector< double > &params)
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