CMS 3D CMS Logo

RunManagerMTWorker.cc
Go to the documentation of this file.
13 
20 
28 
34 
38 
41 
43 
45 
47 
48 #include "G4Event.hh"
49 #include "G4Run.hh"
50 #include "G4SystemOfUnits.hh"
51 #include "G4Threading.hh"
52 #include "G4UImanager.hh"
53 #include "G4WorkerThread.hh"
54 #include "G4WorkerRunManagerKernel.hh"
55 #include "G4StateManager.hh"
56 #include "G4TransportationManager.hh"
57 
58 #include <atomic>
59 #include <thread>
60 #include <sstream>
61 #include <vector>
62 
63 // from https://hypernews.cern.ch/HyperNews/CMS/get/edmFramework/3302/2.html
64 namespace {
65  std::atomic<int> thread_counter{ 0 };
66 
67  int get_new_thread_index() {
68  return thread_counter++;
69  }
70 
71  thread_local int s_thread_index = get_new_thread_index();
72 
73  int getThreadIndex() { return s_thread_index; }
74 
75  void createWatchers(const edm::ParameterSet& iP,
76  SimActivityRegistry& iReg,
77  std::vector<std::shared_ptr<SimWatcher> >& oWatchers,
78  std::vector<std::shared_ptr<SimProducer> >& oProds,
79  int thisThreadID
80  )
81  {
82  if(!iP.exists("Watchers")) { return; }
83 
84  std::vector<edm::ParameterSet> watchers =
85  iP.getParameter<std::vector<edm::ParameterSet> >("Watchers");
86 
87  for(auto & watcher : watchers) {
88  std::unique_ptr<SimWatcherMakerBase> maker(
89  SimWatcherFactory::get()->create(watcher.getParameter<std::string>("type"))
90  );
91  if(maker.get()==nullptr) {
93  << "Unable to find the requested Watcher <"
94  << watcher.getParameter<std::string>("type");
95  }
96  std::shared_ptr<SimWatcher> watcherTemp;
97  std::shared_ptr<SimProducer> producerTemp;
98  maker->make(watcher,iReg,watcherTemp,producerTemp);
99  oWatchers.push_back(watcherTemp);
100  if(producerTemp) {
101  oProds.push_back(producerTemp);
102  }
103  }
104  }
105 }
106 
108  std::unique_ptr<CustomUIsession> UIsession;
109  std::unique_ptr<RunAction> userRunAction;
110  std::unique_ptr<SimRunInterface> runInterface;
112  std::unique_ptr<SimTrackManager> trackManager;
113  std::vector<SensitiveTkDetector*> sensTkDets;
114  std::vector<SensitiveCaloDetector*> sensCaloDets;
115  std::vector<std::shared_ptr<SimWatcher> > watchers;
116  std::vector<std::shared_ptr<SimProducer> > producers;
117  std::unique_ptr<G4Run> currentRun;
118  std::unique_ptr<G4Event> currentEvent;
120  G4RunManagerKernel* kernel = nullptr;
121  bool threadInitialized = false;
122  bool runTerminated = false;
123 };
124 
126 
128  m_generator(iConfig.getParameter<edm::ParameterSet>("Generator")),
129  m_InToken(iC.consumes<edm::HepMCProduct>(iConfig.getParameter<edm::ParameterSet>("Generator").getParameter<edm::InputTag>("HepMCProductLabel"))),
130  m_theLHCTlinkToken(iC.consumes<edm::LHCTransportLinkContainer>(iConfig.getParameter<edm::InputTag>("theLHCTlinkTag"))),
131  m_nonBeam(iConfig.getParameter<bool>("NonBeamEvent")),
132  m_pUseMagneticField(iConfig.getParameter<bool>("UseMagneticField")),
133  m_EvtMgrVerbosity(iConfig.getUntrackedParameter<int>("G4EventManagerVerbosity",0)),
134  m_pField(iConfig.getParameter<edm::ParameterSet>("MagneticField")),
135  m_pRunAction(iConfig.getParameter<edm::ParameterSet>("RunAction")),
136  m_pEventAction(iConfig.getParameter<edm::ParameterSet>("EventAction")),
137  m_pStackingAction(iConfig.getParameter<edm::ParameterSet>("StackingAction")),
138  m_pTrackingAction(iConfig.getParameter<edm::ParameterSet>("TrackingAction")),
139  m_pSteppingAction(iConfig.getParameter<edm::ParameterSet>("SteppingAction")),
140  m_pCustomUIsession(iConfig.getUntrackedParameter<edm::ParameterSet>("CustomUIsession")),
141  m_p(iConfig)
142 {
143  initializeTLS();
144  m_simEvent.reset(nullptr);
145  m_sVerbose.reset(nullptr);
146  std::vector<edm::ParameterSet> watchers =
147  iConfig.getParameter<std::vector<edm::ParameterSet> >("Watchers");
148  m_hasWatchers = (watchers.empty()) ? false : true;
149 }
150 
152  if(m_tls && !m_tls->runTerminated) { terminateRun(); }
153 }
154 
156  terminateRun();
157 }
158 
160  if(m_tls) { return; }
161  m_tls = new TLSData;
162 
163  edm::Service<SimActivityRegistry> otherRegistry;
164  //Look for an outside SimActivityRegistry
165  // this is used by the visualization code
166  int thisID = getThreadIndex();
167  if(otherRegistry){
168  m_tls->registry.connect(*otherRegistry);
169  if(thisID > 0) {
170  throw edm::Exception(edm::errors::Configuration) << "SimActivityRegistry service (i.e. visualization) is not supported for more than 1 thread. If this use case is needed, RunManagerMTWorker has to be updated.";
171  }
172  }
173  if(m_hasWatchers) {
175  }
176 }
177 
179  // I guess everything initialized here should be in thread_local storage
180  initializeTLS();
181 
182  int thisID = getThreadIndex();
183 
184  edm::LogInfo("SimG4CoreApplication")
185  << "RunManagerMTWorker::initializeThread " << thisID;
186 
187  // Initialize per-thread output
188  G4Threading::G4SetThreadId( thisID );
189  G4UImanager::GetUIpointer()->SetUpForAThread( thisID );
191  if(uitype == "MessageLogger") {
192  m_tls->UIsession.reset(new CustomUIsession());
193  }
194  else if(uitype == "MessageLoggerThreadPrefix") {
196  }
197  else if(uitype == "FilePerThread") {
199  }
200  else {
202  << "Invalid value of CustomUIsession.Type '" << uitype
203  << "', valid are MessageLogger, MessageLoggerThreadPrefix, FilePerThread";
204  }
205 
206  // Initialize worker part of shared resources (geometry, physics)
207  G4WorkerThread::BuildGeometryAndPhysicsVector();
208 
209  // Create worker run manager
210  m_tls->kernel = G4WorkerRunManagerKernel::GetRunManagerKernel();
211  if(!m_tls->kernel) { m_tls->kernel = new G4WorkerRunManagerKernel(); }
212 
213  // Define G4 exception handler
214  G4StateManager::GetStateManager()->SetExceptionHandler(new ExceptionHandler());
215 
216  // Set the geometry for the worker, share from master
218 
219  // we need the track manager now
220  m_tls->trackManager.reset(new SimTrackManager());
221 
222  // Get DDCompactView, or would it be better to get the object from
223  // runManagerMaster instead of EventSetup in here?
225  es.get<IdealGeometryRecord>().get(pDD);
226 
227  // setup the magnetic field
229  {
230  const GlobalPoint g(0.,0.,0.);
231 
233  es.get<IdealMagneticFieldRecord>().get(pMF);
234 
235  sim::FieldBuilder fieldBuilder(pMF.product(), m_pField);
236  CMSFieldManager* fieldManager = new CMSFieldManager();
237  G4TransportationManager * tM =
238  G4TransportationManager::GetTransportationManager();
239  tM->SetFieldManager(fieldManager);
240  fieldBuilder.build( fieldManager, tM->GetPropagatorInField());
241  }
242 
243  // attach sensitive detector
244  AttachSD attach;
245  std::pair< std::vector<SensitiveTkDetector*>,
246  std::vector<SensitiveCaloDetector*> > sensDets =
247  attach.create(runManagerMaster.world(),
248  (*pDD),
249  runManagerMaster.catalog(),
250  m_p,
251  m_tls->trackManager.get(),
252  m_tls->registry);
253 
254  m_tls->sensTkDets.swap(sensDets.first);
255  m_tls->sensCaloDets.swap(sensDets.second);
256 
257  edm::LogInfo("SimG4CoreApplication")
258  << " RunManagerMTWorker: Sensitive Detector "
259  << "building finished; found "
260  << m_tls->sensTkDets.size()
261  << " Tk type Producers, and "
262  << m_tls->sensCaloDets.size()
263  << " Calo type producers ";
264 
265  // Set the physics list for the worker, share from master
266  PhysicsList *physicsList = runManagerMaster.physicsListForWorker();
267 
268  edm::LogInfo("SimG4CoreApplication")
269  << "RunManagerMTWorker: start initialisation of PhysicsList for a thread";
270 
271  physicsList->InitializeWorker();
272  m_tls->kernel->SetPhysics(physicsList);
273  m_tls->kernel->InitializePhysics();
274 
275  const bool kernelInit = m_tls->kernel->RunInitialization();
276  if(!kernelInit) {
277  throw SimG4Exception("G4WorkerRunManagerKernel initialization failed");
278  }
279  //tell all interesting parties that we are beginning the job
280  BeginOfJob aBeginOfJob(&es);
281  m_tls->registry.beginOfJobSignal_(&aBeginOfJob);
282 
283  G4int sv = m_p.getParameter<int>("SteppingVerbosity");
284  G4double elim = m_p.getParameter<double>("StepVerboseThreshold")*CLHEP::GeV;
285  std::vector<int> ve = m_p.getParameter<std::vector<int> >("VerboseEvents");
286  std::vector<int> vn = m_p.getParameter<std::vector<int> >("VertexNumber");
287  std::vector<int> vt = m_p.getParameter<std::vector<int> >("VerboseTracks");
288 
289  if(sv > 0) {
290  m_sVerbose.reset(new CMSSteppingVerbose(sv, elim, ve, vn, vt));
291  }
293 
294  edm::LogInfo("SimG4CoreApplication")
295  << "RunManagerMTWorker::initializeThread done for the thread " << thisID;
296 
297  for(const std::string& command: runManagerMaster.G4Commands()) {
298  edm::LogInfo("SimG4CoreApplication") << "RunManagerMTWorker:: Requests UI: "
299  << command;
300  G4UImanager::GetUIpointer()->ApplyCommand(command);
301  }
302 }
303 
305  m_tls->runInterface.reset(new SimRunInterface(this, false));
307  m_tls->runInterface.get(),false));
308  m_tls->userRunAction->SetMaster(false);
309  Connect(m_tls->userRunAction.get());
310 
311  G4EventManager * eventManager = m_tls->kernel->GetEventManager();
312  eventManager->SetVerboseLevel(m_EvtMgrVerbosity);
313 
314  EventAction * userEventAction =
316  m_tls->trackManager.get(), m_sVerbose.get());
317  Connect(userEventAction);
318  eventManager->SetUserAction(userEventAction);
319 
320  TrackingAction* userTrackingAction =
321  new TrackingAction(userEventAction, m_pTrackingAction, m_sVerbose.get());
322  Connect(userTrackingAction);
323  eventManager->SetUserAction(userTrackingAction);
324 
325  SteppingAction* userSteppingAction =
326  new SteppingAction(userEventAction,m_pSteppingAction,m_sVerbose.get(),m_hasWatchers);
327  Connect(userSteppingAction);
328  eventManager->SetUserAction(userSteppingAction);
329 
330  eventManager->SetUserAction(new StackingAction(userTrackingAction,
332 
333 }
334 
336 {
339 }
340 
342 {
345 }
346 
348 {
351 }
352 
354 {
356 }
357 
359  initializeTLS();
360  return m_tls->trackManager.get();
361 }
362 std::vector<SensitiveTkDetector*>& RunManagerMTWorker::sensTkDetectors() {
363  initializeTLS();
364  return m_tls->sensTkDets;
365 }
366 std::vector<SensitiveCaloDetector*>& RunManagerMTWorker::sensCaloDetectors() {
367  initializeTLS();
368  return m_tls->sensCaloDets;
369 }
370 std::vector<std::shared_ptr<SimProducer> > RunManagerMTWorker::producers() {
371  initializeTLS();
372  return m_tls->producers;
373 }
374 
376  m_tls->currentRun.reset(new G4Run());
377  G4StateManager::GetStateManager()->SetNewState(G4State_GeomClosed);
378  if (m_tls->userRunAction) { m_tls->userRunAction->BeginOfRunAction(m_tls->currentRun.get()); }
379 }
380 
382  if(!m_tls || m_tls->runTerminated) { return; }
383  if(m_tls->userRunAction) {
384  m_tls->userRunAction->EndOfRunAction(m_tls->currentRun.get());
385  m_tls->userRunAction.reset();
386  }
387  m_tls->currentEvent.reset();
388  m_simEvent.reset();
389 
390  if(m_tls->kernel) {
391  m_tls->kernel->RunTermination();
392  }
393 
394  m_tls->runTerminated = true;
395 }
396 
398  RunManagerMT& runManagerMaster) {
399  // The initialization and begin/end run is a bit convoluted due to
400  // - Geant4 deals per-thread
401  // - OscarMTProducer deals per-stream
402  // and framework/TBB is free to schedule work in streams to the
403  // threads as it likes.
404  //
405  // We have to do the per-thread initialization, and per-thread
406  // per-run initialization here by ourselves.
407 
408  if(!(m_tls && m_tls->threadInitialized)) {
409  LogDebug("SimG4CoreApplication")
410  << "RunManagerMTWorker::produce(): stream "
411  << inpevt.streamID() << " thread " << getThreadIndex() << " initializing";
412  initializeThread(runManagerMaster, es);
413  m_tls->threadInitialized = true;
414  }
415  // Initialize run
416  if(inpevt.id().run() != m_tls->currentRunNumber) {
417  if(m_tls->currentRunNumber != 0 && !m_tls->runTerminated) {
418  // If previous run in this thread was not terminated via endRun() call, terminate it now
419  terminateRun();
420  }
421  initializeRun();
422  m_tls->currentRunNumber = inpevt.id().run();
423  }
424  m_tls->runInterface->setRunManagerMTWorker(this); // For UserActions
425 
426  m_tls->currentEvent.reset(generateEvent(inpevt));
427 
428  m_simEvent.reset(new G4SimEvent());
429  m_simEvent->hepEvent(m_generator.genEvent());
431  if (m_generator.genVertex() != nullptr ) {
432  auto genVertex = m_generator.genVertex();
433  m_simEvent->collisionPoint(
434  math::XYZTLorentzVectorD(genVertex->x()/centimeter,
435  genVertex->y()/centimeter,
436  genVertex->z()/centimeter,
437  genVertex->t()/second));
438  }
439  if (m_tls->currentEvent->GetNumberOfPrimaryVertex()==0) {
440  std::stringstream ss;
441  ss << "RunManagerMTWorker::produce(): event " << inpevt.id().event()
442  << " with no G4PrimaryVertices \n" ;
443  throw SimG4Exception(ss.str());
444 
445  } else {
446  if(!m_tls->kernel) {
447  std::stringstream ss;
448  ss << " RunManagerMT::produce(): "
449  << " no G4WorkerRunManagerKernel yet for thread index"
450  << getThreadIndex() << ", id " << std::hex
451  << std::this_thread::get_id() << " \n";
452  throw SimG4Exception(ss.str());
453  }
454 
455  edm::LogInfo("SimG4CoreApplication")
456  << " RunManagerMTWorker::produce: start Event " << inpevt.id().event()
457  << " stream id " << inpevt.streamID()
458  << " thread index " << getThreadIndex()
459  << " of weight " << m_simEvent->weight()
460  << " with " << m_simEvent->nTracks() << " tracks and "
461  << m_simEvent->nVertices()
462  << " vertices, generated by " << m_simEvent->nGenParts() << " particles ";
463 
464  m_tls->kernel->GetEventManager()->ProcessOneEvent(m_tls->currentEvent.get());
465 
466  edm::LogInfo("SimG4CoreApplication")
467  << " RunManagerMTWorker::produce: ended Event " << inpevt.id().event();
468  }
469 }
470 
472  if(m_tls->runTerminated) { return; }
473  G4Track* t = m_tls->kernel->GetEventManager()->GetTrackingManager()->GetTrack();
474  t->SetTrackStatus(fStopAndKill) ;
475 
476  // CMS-specific act
477  //
478  TrackingAction* uta =
479  static_cast<TrackingAction *>(m_tls->kernel->GetEventManager()->GetUserTrackingAction());
480  uta->PostUserTrackingAction(t) ;
481 
482  m_tls->currentEvent->SetEventAborted();
483  m_tls->kernel->GetEventManager()->GetStackManager()->clear();
484  m_tls->kernel->GetEventManager()->GetTrackingManager()->EventAborted();
485 }
486 
487 void RunManagerMTWorker::abortRun(bool softAbort) {
488  if (!softAbort) { abortEvent(); }
489  m_tls->currentRun.reset();
490  terminateRun();
491 }
492 
494  m_tls->currentEvent.reset();
495  m_simEvent.reset();
496 
497  // 64 bits event ID in CMSSW converted into Geant4 event ID
498  G4int evtid = (G4int)inpevt.id().event();
499  G4Event * evt = new G4Event(evtid);
500 
502 
503  inpevt.getByToken(m_InToken, HepMCEvt);
504 
505  m_generator.setGenEvent(HepMCEvt->GetEvent());
506 
507  // required to reset the GenParticle Id for particles transported
508  // along the beam pipe
509  // to their original value for SimTrack creation
510  resetGenParticleId( inpevt );
511 
512  if (!m_nonBeam)
513  {
514  m_generator.HepMC2G4(HepMCEvt->GetEvent(),evt);
515  }
516  else
517  {
518  m_generator.nonBeamEvent2G4(HepMCEvt->GetEvent(),evt);
519  }
520 
521  return evt;
522 }
523 
525 {
527  inpevt.getByToken( m_theLHCTlinkToken, theLHCTlink );
528  if ( theLHCTlink.isValid() ) {
529  m_tls->trackManager->setLHCTransportLink( theLHCTlink.product() );
530  }
531 }
#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:79
T getUntrackedParameter(std::string const &, T const &) const
virtual const math::XYZTLorentzVector * genVertex() const
Definition: Generator.h:30
const double GeV
Definition: MathUtil.h:16
std::unique_ptr< G4Event > currentEvent
virtual const double eventWeight() const
Definition: Generator.h:31
std::pair< std::vector< SensitiveTkDetector * >, std::vector< SensitiveCaloDetector * > > create(const DDDWorld &, const DDCompactView &, const SensitiveDetectorCatalog &, edm::ParameterSet const &, const SimTrackManager *, SimActivityRegistry &reg) const
Definition: AttachSD.cc:15
ROOT::Math::LorentzVector< ROOT::Math::PxPyPzE4D< double > > XYZTLorentzVectorD
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:14
def create(alignables, pedeDump, additionalData, outputFile, config)
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:579
void connect(Observer< const BeginOfJob * > *iObject)
void HepMC2G4(const HepMC::GenEvent *g, G4Event *e)
Definition: Generator.cc:104
EndOfEventSignal endOfEventSignal_
std::unique_ptr< SimRunInterface > runInterface
std::unique_ptr< CMSSteppingVerbose > m_sVerbose
SimActivityRegistry::EndOfRunSignal m_endOfRunSignal
Definition: RunAction.h:26
bool exists(std::string const &parameterName) const
checks if a parameter exists
BeginOfRunSignal beginOfRunSignal_
std::vector< SensitiveTkDetector * > sensTkDets
SimActivityRegistry::EndOfEventSignal m_endOfEventSignal
Definition: EventAction.h:51
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:87
#define nullptr
edm::EDGetTokenT< edm::HepMCProduct > m_InToken
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:75
RunAction
list of unwanted particles (gluons and quarks)
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 initializeThread(RunManagerMT &runManagerMaster, const edm::EventSetup &es)
void setGenEvent(const HepMC::GenEvent *inpevt)
Definition: Generator.h:25
BeginOfEventSignal beginOfEventSignal_
SimActivityRegistry::EndOfTrackSignal m_endOfTrackSignal
bool isValid() const
Definition: HandleBase.h:74
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:90
const HepMC::GenEvent * GetEvent() const
Definition: HepMCProduct.h:38
T const * product() const
Definition: Handle.h:81
std::vector< SensitiveCaloDetector * > & sensCaloDetectors()
edm::ParameterSet m_pTrackingAction
void produce(const edm::Event &inpevt, const edm::EventSetup &es, RunManagerMT &runManagerMaster)
std::unique_ptr< G4Run > currentRun
edm::ParameterSet m_pField
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:568
list command
Definition: mps_check.py:23
static void WorkerSetAsWorld(G4VPhysicalVolume *pv)
Definition: DDDWorld.cc:38
SimActivityRegistry::BeginOfRunSignal m_beginOfRunSignal
Definition: RunAction.h:25
const std::vector< std::string > & G4Commands() const
Definition: RunManagerMT.h:83
edm::EventID id() const
Definition: EventBase.h:60
HLT enums.
edm::ParameterSet m_pCustomUIsession
std::vector< std::shared_ptr< SimProducer > > producers()
T get() const
Definition: EventSetup.h:63
StreamID streamID() const
Definition: Event.h:96
std::vector< LHCTransportLink > LHCTransportLinkContainer
void PostUserTrackingAction(const G4Track *aTrack) override
unsigned int RunNumber_t
EndOfTrackSignal endOfTrackSignal_
edm::ParameterSet m_p
T const * product() const
Definition: ESHandle.h:86
SimActivityRegistry::BeginOfEventSignal m_beginOfEventSignal
Definition: EventAction.h:50
T get(const Candidate &c)
Definition: component.h:55
BeginOfTrackSignal beginOfTrackSignal_
edm::ParameterSet m_pStackingAction
void Connect(RunAction *)
SimActivityRegistry::BeginOfTrackSignal m_beginOfTrackSignal