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.
11 
18 
24 
30 
35 
37 
39 
41 
42 #include "G4Event.hh"
43 #include "G4Run.hh"
44 #include "G4SystemOfUnits.hh"
45 #include "G4Threading.hh"
46 #include "G4UImanager.hh"
47 #include "G4WorkerThread.hh"
48 #include "G4WorkerRunManagerKernel.hh"
49 #include "G4StateManager.hh"
50 #include "G4TransportationManager.hh"
51 
52 #include <atomic>
53 #include <thread>
54 #include <sstream>
55 
56 
57 // from https://hypernews.cern.ch/HyperNews/CMS/get/edmFramework/3302/2.html
58 namespace {
59  static std::atomic<int> thread_counter{ 0 };
60 
61  int get_new_thread_index() {
62  return thread_counter++;
63  }
64 
65  static thread_local int s_thread_index = get_new_thread_index();
66 
67  int getThreadIndex() { return s_thread_index; }
68 
69  void createWatchers(const edm::ParameterSet& iP,
70  SimActivityRegistry& iReg,
71  std::vector<std::shared_ptr<SimWatcher> >& oWatchers,
72  std::vector<std::shared_ptr<SimProducer> >& oProds
73  )
74  {
75  using namespace std;
76  using namespace edm;
77  if(!iP.exists("Watchers"))
78  return;
79 
80  vector<ParameterSet> watchers = iP.getParameter<vector<ParameterSet> >("Watchers");
81 
82  for(vector<ParameterSet>::iterator itWatcher = watchers.begin();
83  itWatcher != watchers.end();
84  ++itWatcher) {
85  std::unique_ptr<SimWatcherMakerBase> maker(
86  SimWatcherFactory::get()->create(itWatcher->getParameter<std::string>("type"))
87  );
88  if(maker.get()==0) {
89  throw SimG4Exception("Unable to find the requested Watcher");
90  }
91 
92  std::shared_ptr<SimWatcher> watcherTemp;
93  std::shared_ptr<SimProducer> producerTemp;
94  maker->make(*itWatcher,iReg,watcherTemp,producerTemp);
95  oWatchers.push_back(watcherTemp);
96  if(producerTemp) {
97  oProds.push_back(producerTemp);
98  }
99  }
100  }
101 }
102 
104  std::unique_ptr<CustomUIsession> UIsession;
105  std::unique_ptr<RunAction> userRunAction;
106  std::unique_ptr<SimRunInterface> runInterface;
108  std::unique_ptr<SimTrackManager> trackManager;
109  std::vector<SensitiveTkDetector*> sensTkDets;
110  std::vector<SensitiveCaloDetector*> sensCaloDets;
111  std::vector<std::shared_ptr<SimWatcher> > watchers;
112  std::vector<std::shared_ptr<SimProducer> > producers;
113  std::unique_ptr<sim::FieldBuilder> fieldBuilder;
114  std::unique_ptr<G4Run> currentRun;
116  bool threadInitialized = false;
117  bool runTerminated = false;
118 };
119 
121 
123  m_generator(iConfig.getParameter<edm::ParameterSet>("Generator")),
124  m_InToken(iC.consumes<edm::HepMCProduct>(iConfig.getParameter<edm::ParameterSet>("Generator").getParameter<std::string>("HepMCProductLabel"))),
125  m_theLHCTlinkToken(iC.consumes<edm::LHCTransportLinkContainer>(iConfig.getParameter<edm::InputTag>("theLHCTlinkTag"))),
126  m_nonBeam(iConfig.getParameter<bool>("NonBeamEvent")),
127  m_pUseMagneticField(iConfig.getParameter<bool>("UseMagneticField")),
128  m_EvtMgrVerbosity(iConfig.getUntrackedParameter<int>("G4EventManagerVerbosity",0)),
129  m_pField(iConfig.getParameter<edm::ParameterSet>("MagneticField")),
130  m_pRunAction(iConfig.getParameter<edm::ParameterSet>("RunAction")),
131  m_pEventAction(iConfig.getParameter<edm::ParameterSet>("EventAction")),
132  m_pStackingAction(iConfig.getParameter<edm::ParameterSet>("StackingAction")),
133  m_pTrackingAction(iConfig.getParameter<edm::ParameterSet>("TrackingAction")),
134  m_pSteppingAction(iConfig.getParameter<edm::ParameterSet>("SteppingAction")),
135  m_p(iConfig)
136 {
137  initializeTLS();
138 }
139 
141  if(!(m_tls && m_tls->runTerminated)) { terminateRun(); }
142  // RunManagerMT has 'delete m_runInterface' in the destructor, but
143  // doesn't make much sense here because it is thread_local and we're
144  // not guaranteed to run the destructor on each of the threads.
145 }
146 
148  terminateRun();
149 }
150 
152  if(m_tls)
153  return;
154  m_tls = new TLSData;
155 
156  edm::Service<SimActivityRegistry> otherRegistry;
157  //Look for an outside SimActivityRegistry
158  // this is used by the visualization code
159  if(otherRegistry){
160  m_tls->registry.connect(*otherRegistry);
161  }
162 
164 }
165 
166 void RunManagerMTWorker::initializeThread(const RunManagerMT& runManagerMaster, const edm::EventSetup& es) {
167  // I guess everything initialized here should be in thread_local storage
168  initializeTLS();
169 
170  int thisID = getThreadIndex();
171 
172  // Initialize per-thread output
173  G4Threading::G4SetThreadId( thisID );
174  G4UImanager::GetUIpointer()->SetUpForAThread( thisID );
175  m_tls->UIsession.reset(new CustomUIsession());
176 
177  // Initialize worker part of shared resources (geometry, physics)
178  G4WorkerThread::BuildGeometryAndPhysicsVector();
179 
180  // Create worker run manager
181  G4RunManagerKernel *kernel = G4WorkerRunManagerKernel::GetRunManagerKernel();
182  if(!kernel) kernel = new G4WorkerRunManagerKernel();
183 
184  // Set the geometry for the worker, share from master
186 
187  // we need the track manager now
188  m_tls->trackManager.reset(new SimTrackManager());
189 
190  // Get DDCompactView, or would it be better to get the object from
191  // runManagerMaster instead of EventSetup in here?
193  es.get<IdealGeometryRecord>().get(pDD);
194 
195  // setup the magnetic field
197  {
198  const GlobalPoint g(0.,0.,0.);
199 
201  es.get<IdealMagneticFieldRecord>().get(pMF);
202 
204  G4TransportationManager * tM =
205  G4TransportationManager::GetTransportationManager();
206  m_tls->fieldBuilder->build( tM->GetFieldManager(),
207  tM->GetPropagatorInField());
208  }
209 
210 
211  // attach sensitive detector
212  AttachSD attach;
213  std::pair< std::vector<SensitiveTkDetector*>,
214  std::vector<SensitiveCaloDetector*> > sensDets =
215  attach.create(runManagerMaster.world(),
216  (*pDD),
217  runManagerMaster.catalog(),
218  m_p,
219  m_tls->trackManager.get(),
220  m_tls->registry);
221 
222  m_tls->sensTkDets.swap(sensDets.first);
223  m_tls->sensCaloDets.swap(sensDets.second);
224 
225  edm::LogInfo("SimG4CoreApplication")
226  << " RunManagerMTWorker: Sensitive Detector "
227  << "building finished; found "
228  << m_tls->sensTkDets.size()
229  << " Tk type Producers, and "
230  << m_tls->sensCaloDets.size()
231  << " Calo type producers ";
232 
233  // Set the physics list for the worker, share from master
234  PhysicsList *physicsList = runManagerMaster.physicsListForWorker();
235  physicsList->InitializeWorker();
236  kernel->SetPhysics(physicsList);
237  kernel->InitializePhysics();
238 
239  const bool kernelInit = kernel->RunInitialization();
240  if(!kernelInit)
241  throw SimG4Exception("G4WorkerRunManagerKernel initialization failed");
242 
243  //tell all interesting parties that we are beginning the job
244  BeginOfJob aBeginOfJob(&es);
245  m_tls->registry.beginOfJobSignal_(&aBeginOfJob);
246 
248 
249  for(const std::string& command: runManagerMaster.G4Commands()) {
250  edm::LogInfo("SimG4CoreApplication") << "RunManagerMTWorker:: Requests UI: "
251  << command;
252  G4UImanager::GetUIpointer()->ApplyCommand(command);
253  }
254 }
255 
257  m_tls->runInterface.reset(new SimRunInterface(this, false));
258 
260  m_tls->userRunAction->SetMaster(false);
261  Connect(m_tls->userRunAction.get());
262 
263  G4RunManagerKernel *kernel = G4WorkerRunManagerKernel::GetRunManagerKernel();
264  G4EventManager * eventManager = kernel->GetEventManager();
265  eventManager->SetVerboseLevel(m_EvtMgrVerbosity);
266 
267  EventAction * userEventAction =
269  Connect(userEventAction);
270  eventManager->SetUserAction(userEventAction);
271 
272  TrackingAction* userTrackingAction =
273  new TrackingAction(userEventAction,m_pTrackingAction);
274  Connect(userTrackingAction);
275  eventManager->SetUserAction(userTrackingAction);
276 
277  SteppingAction* userSteppingAction =
278  new SteppingAction(userEventAction,m_pSteppingAction);
279  Connect(userSteppingAction);
280  eventManager->SetUserAction(userSteppingAction);
281 
282  eventManager->SetUserAction(new StackingAction(userTrackingAction,
284 
285 }
286 
288 {
291 }
292 
294 {
297 }
298 
300 {
303 }
304 
306 {
308 }
309 
311  initializeTLS();
312  return m_tls->trackManager.get();
313 }
314 std::vector<SensitiveTkDetector*>& RunManagerMTWorker::sensTkDetectors() {
315  initializeTLS();
316  return m_tls->sensTkDets;
317 }
318 std::vector<SensitiveCaloDetector*>& RunManagerMTWorker::sensCaloDetectors() {
319  initializeTLS();
320  return m_tls->sensCaloDets;
321 }
322 std::vector<std::shared_ptr<SimProducer> > RunManagerMTWorker::producers() {
323  initializeTLS();
324  return m_tls->producers;
325 }
326 
327 
329  m_tls->currentRun.reset(new G4Run());
330  G4StateManager::GetStateManager()->SetNewState(G4State_GeomClosed);
331  if (m_tls->userRunAction) { m_tls->userRunAction->BeginOfRunAction(m_tls->currentRun.get()); }
332 }
333 
335  if(m_tls->userRunAction) {
336  m_tls->userRunAction->EndOfRunAction(m_tls->currentRun.get());
337  m_tls->userRunAction.reset();
338  }
339 
340  G4RunManagerKernel *kernel = G4WorkerRunManagerKernel::GetRunManagerKernel();
341  if(!kernel && !m_tls->runTerminated) {
342  m_currentEvent.reset();
343  m_simEvent.reset();
344  kernel->RunTermination();
345  m_tls->runTerminated = true;
346  }
347 }
348 
349 void RunManagerMTWorker::produce(const edm::Event& inpevt, const edm::EventSetup& es, const RunManagerMT& runManagerMaster) {
350  // The initialization and begin/end run is a bit convoluted due to
351  // - Geant4 deals per-thread
352  // - OscarMTProducer deals per-stream
353  // and framework/TBB is free to schedule work in streams to the
354  // threads as it likes.
355  //
356  // We have to do the per-thread initialization, and per-thread
357  // per-run initialization here by ourselves.
358  if(!(m_tls && m_tls->threadInitialized)) {
359  LogDebug("SimG4CoreApplication") << "RunManagerMTWorker::produce(): stream " << inpevt.streamID() << " thread " << getThreadIndex() << " initializing";
360  initializeThread(runManagerMaster, es);
361  m_tls->threadInitialized = true;
362  }
363  // Initialize run
364  if(inpevt.id().run() != m_tls->currentRunNumber) {
365  if(m_tls->currentRunNumber != 0 && !m_tls->runTerminated) {
366  // If previous run in this thread was not terminated via endRun() call, terminate it now
367  terminateRun();
368  }
369  initializeRun();
370  m_tls->currentRunNumber = inpevt.id().run();
371  }
372  m_tls->runInterface->setRunManagerMTWorker(this); // For UserActions
373 
374 
375  m_currentEvent.reset(generateEvent(inpevt));
376 
377  m_simEvent.reset(new G4SimEvent());
378  m_simEvent->hepEvent(m_generator.genEvent());
380  if (m_generator.genVertex() !=0 ) {
381  auto genVertex = m_generator.genVertex();
382  m_simEvent->collisionPoint(
383  math::XYZTLorentzVectorD(genVertex->x()/centimeter,
384  genVertex->y()/centimeter,
385  genVertex->z()/centimeter,
386  genVertex->t()/second));
387  }
388  if (m_currentEvent->GetNumberOfPrimaryVertex()==0) {
389  edm::LogError("SimG4CoreApplication")
390  << " RunManagerMT::produce event " << inpevt.id().event()
391  << " with no G4PrimaryVertices \n Aborting Run" ;
392 
393  abortRun(false);
394  } else {
395  G4RunManagerKernel *kernel = G4WorkerRunManagerKernel::GetRunManagerKernel();
396  if(!kernel) {
397  std::stringstream ss;
398  ss << "No G4WorkerRunManagerKernel yet for thread index" << getThreadIndex() << ", id " << std::hex << std::this_thread::get_id();
399  throw SimG4Exception(ss.str());
400  }
401  kernel->GetEventManager()->ProcessOneEvent(m_currentEvent.get());
402  }
403 
404  edm::LogInfo("SimG4CoreApplication")
405  << " RunManagerMTWorker: saved : Event " << inpevt.id().event()
406  << " stream id " << inpevt.streamID()
407  << " thread index " << getThreadIndex()
408  << " of weight " << m_simEvent->weight()
409  << " with " << m_simEvent->nTracks() << " tracks and "
410  << m_simEvent->nVertices()
411  << " vertices, generated by " << m_simEvent->nGenParts() << " particles ";
412 }
413 
415  if(m_tls->runTerminated) { return; }
416  G4RunManagerKernel *kernel = G4WorkerRunManagerKernel::GetRunManagerKernel();
417  G4Track* t = kernel->GetEventManager()->GetTrackingManager()->GetTrack();
418  t->SetTrackStatus(fStopAndKill) ;
419 
420  // CMS-specific act
421  //
422  TrackingAction* uta =
423  static_cast<TrackingAction *>(kernel->GetEventManager()->GetUserTrackingAction());
424  uta->PostUserTrackingAction(t) ;
425 
426  m_currentEvent->SetEventAborted();
427 
428  // do NOT call this method for now
429  // because it'll set abortRequested=true (withing G4EventManager)
430  // this will make Geant4, in the event *next* after the aborted one
431  // NOT to get the primary, thus there's NOTHING to trace, and it goes
432  // to the end of G4Event::DoProcessing(G4Event*), where abortRequested
433  // will be reset to true again
434  //
435  //kernel->GetEventManager()->AbortCurrentEvent();
436  //
437  // instead, mimic what it does, except (re)setting abortRequested
438  //
439  kernel->GetEventManager()->GetStackManager()->clear() ;
440  kernel->GetEventManager()->GetTrackingManager()->EventAborted() ;
441 
442  G4StateManager* stateManager = G4StateManager::GetStateManager();
443  stateManager->SetNewState(G4State_GeomClosed);
444 }
445 
446 void RunManagerMTWorker::abortRun(bool softAbort) {
447  if (!softAbort) { abortEvent(); }
448  m_tls->currentRun.reset();
449  terminateRun();
450 }
451 
453  m_currentEvent.reset();
454  m_simEvent.reset();
455 
456  G4Event * evt = new G4Event(inpevt.id().event());
458 
459  inpevt.getByToken(m_InToken, HepMCEvt);
460 
461  m_generator.setGenEvent(HepMCEvt->GetEvent());
462 
463  // required to reset the GenParticle Id for particles transported
464  // along the beam pipe
465  // to their original value for SimTrack creation
466  resetGenParticleId( inpevt );
467 
468  if (!m_nonBeam)
469  {
470  m_generator.HepMC2G4(HepMCEvt->GetEvent(),evt);
471  }
472  else
473  {
474  m_generator.nonBeamEvent2G4(HepMCEvt->GetEvent(),evt);
475  }
476 
477  return evt;
478 }
479 
481 {
483  inpevt.getByToken( m_theLHCTlinkToken, theLHCTlink );
484  if ( theLHCTlink.isValid() ) {
485  m_tls->trackManager->setLHCTransportLink( theLHCTlink.product() );
486  }
487 }
#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:83
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:23
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:79
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_
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: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: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:508
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:22
const std::vector< std::string > & G4Commands() const
Definition: RunManagerMT.h:87
edm::EventID id() const
Definition: EventBase.h:56
std::vector< std::shared_ptr< SimProducer > > producers()
StreamID streamID() const
Definition: Event.h:72
std::vector< LHCTransportLink > LHCTransportLinkContainer
unsigned int RunNumber_t
Definition: EventRange.h:32
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