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;
123  bool threadInitialized = false;
124  bool runTerminated = false;
125 };
126 
128 
130  m_generator(iConfig.getParameter<edm::ParameterSet>("Generator")),
131  m_InToken(iC.consumes<edm::HepMCProduct>(iConfig.getParameter<edm::ParameterSet>("Generator").getParameter<std::string>("HepMCProductLabel"))),
132  m_theLHCTlinkToken(iC.consumes<edm::LHCTransportLinkContainer>(iConfig.getParameter<edm::InputTag>("theLHCTlinkTag"))),
133  m_nonBeam(iConfig.getParameter<bool>("NonBeamEvent")),
134  m_pUseMagneticField(iConfig.getParameter<bool>("UseMagneticField")),
135  m_EvtMgrVerbosity(iConfig.getUntrackedParameter<int>("G4EventManagerVerbosity",0)),
136  m_pField(iConfig.getParameter<edm::ParameterSet>("MagneticField")),
137  m_pRunAction(iConfig.getParameter<edm::ParameterSet>("RunAction")),
138  m_pEventAction(iConfig.getParameter<edm::ParameterSet>("EventAction")),
139  m_pStackingAction(iConfig.getParameter<edm::ParameterSet>("StackingAction")),
140  m_pTrackingAction(iConfig.getParameter<edm::ParameterSet>("TrackingAction")),
141  m_pSteppingAction(iConfig.getParameter<edm::ParameterSet>("SteppingAction")),
142  m_pCustomUIsession(iConfig.getUntrackedParameter<edm::ParameterSet>("CustomUIsession")),
143  m_p(iConfig)
144 {
145  initializeTLS();
146 }
147 
149  if(!(m_tls && m_tls->runTerminated)) { terminateRun(); }
150  // RunManagerMT has 'delete m_runInterface' in the destructor, but
151  // doesn't make much sense here because it is thread_local and we're
152  // not guaranteed to run the destructor on each of the threads.
153 }
154 
156  terminateRun();
157 }
158 
160  if(m_tls)
161  return;
162  m_tls = new TLSData;
163 
164  edm::Service<SimActivityRegistry> otherRegistry;
165  //Look for an outside SimActivityRegistry
166  // this is used by the visualization code
167  int thisID = getThreadIndex();
168  if(otherRegistry){
169  m_tls->registry.connect(*otherRegistry);
170  if(thisID > 0) {
171  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.";
172  }
173  }
174 
176 }
177 
178 void RunManagerMTWorker::initializeThread(const RunManagerMT& runManagerMaster, const edm::EventSetup& es) {
179  // I guess everything initialized here should be in thread_local storage
180  initializeTLS();
181 
182  int thisID = getThreadIndex();
183 
184  // Initialize per-thread output
185  G4Threading::G4SetThreadId( thisID );
186  G4UImanager::GetUIpointer()->SetUpForAThread( thisID );
188  if(uitype == "MessageLogger") {
189  m_tls->UIsession.reset(new CustomUIsession());
190  }
191  else if(uitype == "MessageLoggerThreadPrefix") {
193  }
194  else if(uitype == "FilePerThread") {
196  }
197  else {
198  throw cms::Exception("Configuration") << "Invalid value of CustomUIsession.Type '" << uitype << "', valid are MessageLogger, MessageLoggerThreadPrefix, FilePerThread";
199  }
200 
201  // Initialize worker part of shared resources (geometry, physics)
202  G4WorkerThread::BuildGeometryAndPhysicsVector();
203 
204  // Create worker run manager
205  G4RunManagerKernel *kernel = G4WorkerRunManagerKernel::GetRunManagerKernel();
206  if(!kernel) kernel = new G4WorkerRunManagerKernel();
207 
208  // Set the geometry for the worker, share from master
210 
211  // we need the track manager now
212  m_tls->trackManager.reset(new SimTrackManager());
213 
214  // Get DDCompactView, or would it be better to get the object from
215  // runManagerMaster instead of EventSetup in here?
217  es.get<IdealGeometryRecord>().get(pDD);
218 
219  // setup the magnetic field
221  {
222  const GlobalPoint g(0.,0.,0.);
223 
225  es.get<IdealMagneticFieldRecord>().get(pMF);
226 
228  G4TransportationManager * tM =
229  G4TransportationManager::GetTransportationManager();
230  m_tls->fieldBuilder->build( tM->GetFieldManager(),
231  tM->GetPropagatorInField(),
232  runManagerMaster.chordFinderSetterForWorker());
233  }
234 
235 
236  // attach sensitive detector
237  AttachSD attach;
238  std::pair< std::vector<SensitiveTkDetector*>,
239  std::vector<SensitiveCaloDetector*> > sensDets =
240  attach.create(runManagerMaster.world(),
241  (*pDD),
242  runManagerMaster.catalog(),
243  m_p,
244  m_tls->trackManager.get(),
245  m_tls->registry);
246 
247  m_tls->sensTkDets.swap(sensDets.first);
248  m_tls->sensCaloDets.swap(sensDets.second);
249 
250  edm::LogInfo("SimG4CoreApplication")
251  << " RunManagerMTWorker: Sensitive Detector "
252  << "building finished; found "
253  << m_tls->sensTkDets.size()
254  << " Tk type Producers, and "
255  << m_tls->sensCaloDets.size()
256  << " Calo type producers ";
257 
258  // Set the physics list for the worker, share from master
259  PhysicsList *physicsList = runManagerMaster.physicsListForWorker();
260  physicsList->InitializeWorker();
261  kernel->SetPhysics(physicsList);
262  kernel->InitializePhysics();
263 
264  const bool kernelInit = kernel->RunInitialization();
265  if(!kernelInit)
266  throw SimG4Exception("G4WorkerRunManagerKernel initialization failed");
267 
268  //tell all interesting parties that we are beginning the job
269  BeginOfJob aBeginOfJob(&es);
270  m_tls->registry.beginOfJobSignal_(&aBeginOfJob);
271 
273 
274  for(const std::string& command: runManagerMaster.G4Commands()) {
275  edm::LogInfo("SimG4CoreApplication") << "RunManagerMTWorker:: Requests UI: "
276  << command;
277  G4UImanager::GetUIpointer()->ApplyCommand(command);
278  }
279 }
280 
282  m_tls->runInterface.reset(new SimRunInterface(this, false));
283 
285  m_tls->userRunAction->SetMaster(false);
286  Connect(m_tls->userRunAction.get());
287 
288  G4RunManagerKernel *kernel = G4WorkerRunManagerKernel::GetRunManagerKernel();
289  G4EventManager * eventManager = kernel->GetEventManager();
290  eventManager->SetVerboseLevel(m_EvtMgrVerbosity);
291 
292  EventAction * userEventAction =
294  Connect(userEventAction);
295  eventManager->SetUserAction(userEventAction);
296 
297  TrackingAction* userTrackingAction =
298  new TrackingAction(userEventAction,m_pTrackingAction);
299  Connect(userTrackingAction);
300  eventManager->SetUserAction(userTrackingAction);
301 
302  SteppingAction* userSteppingAction =
303  new SteppingAction(userEventAction,m_pSteppingAction);
304  Connect(userSteppingAction);
305  eventManager->SetUserAction(userSteppingAction);
306 
307  eventManager->SetUserAction(new StackingAction(userTrackingAction,
309 
310 }
311 
313 {
316 }
317 
319 {
322 }
323 
325 {
328 }
329 
331 {
333 }
334 
336  initializeTLS();
337  return m_tls->trackManager.get();
338 }
339 std::vector<SensitiveTkDetector*>& RunManagerMTWorker::sensTkDetectors() {
340  initializeTLS();
341  return m_tls->sensTkDets;
342 }
343 std::vector<SensitiveCaloDetector*>& RunManagerMTWorker::sensCaloDetectors() {
344  initializeTLS();
345  return m_tls->sensCaloDets;
346 }
347 std::vector<std::shared_ptr<SimProducer> > RunManagerMTWorker::producers() {
348  initializeTLS();
349  return m_tls->producers;
350 }
351 
352 
354  m_tls->currentRun.reset(new G4Run());
355  G4StateManager::GetStateManager()->SetNewState(G4State_GeomClosed);
356  if (m_tls->userRunAction) { m_tls->userRunAction->BeginOfRunAction(m_tls->currentRun.get()); }
357 }
358 
360  if(m_tls->userRunAction) {
361  m_tls->userRunAction->EndOfRunAction(m_tls->currentRun.get());
362  m_tls->userRunAction.reset();
363  }
364 
365  G4RunManagerKernel *kernel = G4WorkerRunManagerKernel::GetRunManagerKernel();
366  if(!kernel && !m_tls->runTerminated) {
367  m_currentEvent.reset();
368  m_simEvent.reset();
369  kernel->RunTermination();
370  m_tls->runTerminated = true;
371  }
372 }
373 
374 void RunManagerMTWorker::produce(const edm::Event& inpevt, const edm::EventSetup& es, const RunManagerMT& runManagerMaster) {
375  // The initialization and begin/end run is a bit convoluted due to
376  // - Geant4 deals per-thread
377  // - OscarMTProducer deals per-stream
378  // and framework/TBB is free to schedule work in streams to the
379  // threads as it likes.
380  //
381  // We have to do the per-thread initialization, and per-thread
382  // per-run initialization here by ourselves.
383  if(!(m_tls && m_tls->threadInitialized)) {
384  LogDebug("SimG4CoreApplication") << "RunManagerMTWorker::produce(): stream " << inpevt.streamID() << " thread " << getThreadIndex() << " initializing";
385  initializeThread(runManagerMaster, es);
386  m_tls->threadInitialized = true;
387  }
388  // Initialize run
389  if(inpevt.id().run() != m_tls->currentRunNumber) {
390  if(m_tls->currentRunNumber != 0 && !m_tls->runTerminated) {
391  // If previous run in this thread was not terminated via endRun() call, terminate it now
392  terminateRun();
393  }
394  initializeRun();
395  m_tls->currentRunNumber = inpevt.id().run();
396  }
397  m_tls->runInterface->setRunManagerMTWorker(this); // For UserActions
398 
399 
400  m_currentEvent.reset(generateEvent(inpevt));
401 
402  m_simEvent.reset(new G4SimEvent());
403  m_simEvent->hepEvent(m_generator.genEvent());
405  if (m_generator.genVertex() !=0 ) {
406  auto genVertex = m_generator.genVertex();
407  m_simEvent->collisionPoint(
408  math::XYZTLorentzVectorD(genVertex->x()/centimeter,
409  genVertex->y()/centimeter,
410  genVertex->z()/centimeter,
411  genVertex->t()/second));
412  }
413  if (m_currentEvent->GetNumberOfPrimaryVertex()==0) {
414  edm::LogError("SimG4CoreApplication")
415  << " RunManagerMT::produce event " << inpevt.id().event()
416  << " with no G4PrimaryVertices \n Aborting Run" ;
417 
418  abortRun(false);
419  } else {
420  G4RunManagerKernel *kernel = G4WorkerRunManagerKernel::GetRunManagerKernel();
421  if(!kernel) {
422  std::stringstream ss;
423  ss << "No G4WorkerRunManagerKernel yet for thread index" << getThreadIndex() << ", id " << std::hex << std::this_thread::get_id();
424  throw SimG4Exception(ss.str());
425  }
426  kernel->GetEventManager()->ProcessOneEvent(m_currentEvent.get());
427  }
428 
429  edm::LogInfo("SimG4CoreApplication")
430  << " RunManagerMTWorker: saved : Event " << inpevt.id().event()
431  << " stream id " << inpevt.streamID()
432  << " thread index " << getThreadIndex()
433  << " of weight " << m_simEvent->weight()
434  << " with " << m_simEvent->nTracks() << " tracks and "
435  << m_simEvent->nVertices()
436  << " vertices, generated by " << m_simEvent->nGenParts() << " particles ";
437 }
438 
440  if(m_tls->runTerminated) { return; }
441  G4RunManagerKernel *kernel = G4WorkerRunManagerKernel::GetRunManagerKernel();
442  G4Track* t = kernel->GetEventManager()->GetTrackingManager()->GetTrack();
443  t->SetTrackStatus(fStopAndKill) ;
444 
445  // CMS-specific act
446  //
447  TrackingAction* uta =
448  static_cast<TrackingAction *>(kernel->GetEventManager()->GetUserTrackingAction());
449  uta->PostUserTrackingAction(t) ;
450 
451  m_currentEvent->SetEventAborted();
452 
453  // do NOT call this method for now
454  // because it'll set abortRequested=true (withing G4EventManager)
455  // this will make Geant4, in the event *next* after the aborted one
456  // NOT to get the primary, thus there's NOTHING to trace, and it goes
457  // to the end of G4Event::DoProcessing(G4Event*), where abortRequested
458  // will be reset to true again
459  //
460  //kernel->GetEventManager()->AbortCurrentEvent();
461  //
462  // instead, mimic what it does, except (re)setting abortRequested
463  //
464  kernel->GetEventManager()->GetStackManager()->clear() ;
465  kernel->GetEventManager()->GetTrackingManager()->EventAborted() ;
466 
467  G4StateManager* stateManager = G4StateManager::GetStateManager();
468  stateManager->SetNewState(G4State_GeomClosed);
469 }
470 
471 void RunManagerMTWorker::abortRun(bool softAbort) {
472  if (!softAbort) { abortEvent(); }
473  m_tls->currentRun.reset();
474  terminateRun();
475 }
476 
478  m_currentEvent.reset();
479  m_simEvent.reset();
480 
481  // 64 bits event ID in CMSSW converted into Geant4 event ID
482  G4int evtid = (G4int)inpevt.id().event();
483  G4Event * evt = new G4Event(evtid);
484 
486 
487  inpevt.getByToken(m_InToken, HepMCEvt);
488 
489  m_generator.setGenEvent(HepMCEvt->GetEvent());
490 
491  // required to reset the GenParticle Id for particles transported
492  // along the beam pipe
493  // to their original value for SimTrack creation
494  resetGenParticleId( inpevt );
495 
496  if (!m_nonBeam)
497  {
498  m_generator.HepMC2G4(HepMCEvt->GetEvent(),evt);
499  }
500  else
501  {
502  m_generator.nonBeamEvent2G4(HepMCEvt->GetEvent(),evt);
503  }
504 
505  return evt;
506 }
507 
509 {
511  inpevt.getByToken( m_theLHCTlinkToken, theLHCTlink );
512  if ( theLHCTlink.isValid() ) {
513  m_tls->trackManager->setLHCTransportLink( theLHCTlink.product() );
514  }
515 }
#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
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:446
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
std::unique_ptr< G4Event > m_currentEvent
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:76
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:56
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