48 #include "G4SystemOfUnits.hh"
49 #include "G4Threading.hh"
50 #include "G4UImanager.hh"
51 #include "G4WorkerThread.hh"
52 #include "G4WorkerRunManagerKernel.hh"
53 #include "G4StateManager.hh"
54 #include "G4TransportationManager.hh"
56 #include "G4FieldManager.hh"
64 #include "tbb/task_arena.h"
71 std::atomic<int> thread_counter{0};
73 int get_new_thread_index() {
return thread_counter++; }
75 thread_local
int s_thread_index = get_new_thread_index();
77 int getThreadIndex() {
return s_thread_index; }
81 std::vector<std::shared_ptr<SimWatcher>>& oWatchers,
82 std::vector<std::shared_ptr<SimProducer>>& oProds) {
83 if (!iP.
exists(
"Watchers")) {
87 std::vector<edm::ParameterSet> watchers = iP.
getParameter<std::vector<edm::ParameterSet>>(
"Watchers");
89 for (
auto& watcher : watchers) {
90 std::unique_ptr<SimWatcherMakerBase> maker(
92 if (maker ==
nullptr) {
94 <<
"Unable to find the requested Watcher <" << watcher.getParameter<
std::string>(
"type");
96 std::shared_ptr<SimWatcher> watcherTemp;
97 std::shared_ptr<SimProducer> producerTemp;
98 maker->make(watcher, *(iReg), watcherTemp, producerTemp);
99 oWatchers.push_back(watcherTemp);
101 oProds.push_back(producerTemp);
106 std::atomic<int> active_tlsdata{0};
107 std::atomic<bool> tls_shutdown_timeout{
false};
108 std::atomic<int> n_tls_shutdown_task{0};
112 std::unique_ptr<G4RunManagerKernel>
kernel;
148 m_nonBeam(iConfig.getParameter<
bool>(
"NonBeamEvent")),
149 m_pUseMagneticField(iConfig.getParameter<
bool>(
"UseMagneticField")),
150 m_LHCTransport(iConfig.getParameter<
bool>(
"LHCTransport")),
151 m_EvtMgrVerbosity(iConfig.getUntrackedParameter<
int>(
"G4EventManagerVerbosity", 0)),
154 m_pEventAction(iConfig.getParameter<
edm::
ParameterSet>(
"EventAction")),
155 m_pStackingAction(iConfig.getParameter<
edm::
ParameterSet>(
"StackingAction")),
156 m_pTrackingAction(iConfig.getParameter<
edm::
ParameterSet>(
"TrackingAction")),
157 m_pSteppingAction(iConfig.getParameter<
edm::
ParameterSet>(
"SteppingAction")),
158 m_pCustomUIsession(iConfig.getUntrackedParameter<
edm::
ParameterSet>(
"CustomUIsession")),
161 m_sVerbose(nullptr) {
162 std::vector<std::string> onlySDs = iConfig.
getParameter<std::vector<std::string>>(
"OnlySDs");
164 std::vector<edm::ParameterSet> watchers = iConfig.
getParameter<std::vector<edm::ParameterSet>>(
"Watchers");
167 int thisID = getThreadIndex();
174 edm::LogVerbatim(
"SimG4CoreApplication") <<
"RunManagerMTWorker is constructed for the thread " << thisID;
176 for (std::unordered_map<
std::string, std::unique_ptr<SensitiveDetectorMakerBase>>::const_iterator itr =
184 ++n_tls_shutdown_task;
192 while (n_tls_shutdown_task != 0) {
193 nanosleep(&
s,
nullptr);
201 if (active_tlsdata != 0 and not tls_shutdown_timeout) {
202 ++n_tls_shutdown_task;
205 tbb::task_arena arena(tbb::task_arena::attach{});
215 while (active_tlsdata.load() != 0 and ++
count < 1000) {
216 nanosleep(&
s,
nullptr);
219 tls_shutdown_timeout =
true;
222 --n_tls_shutdown_task;
227 maker.second->beginRun(es);
235 int thisID = getThreadIndex();
236 edm::LogVerbatim(
"SimG4CoreApplication") <<
"RunManagerMTWorker::endRun for the thread " << thisID;
241 if (
nullptr !=
m_tls) {
251 int thisID = getThreadIndex();
256 <<
"SimActivityRegistry service (i.e. visualization) is not supported for more than 1 thread. "
257 <<
" \n If this use case is needed, RunManagerMTWorker has to be updated.";
274 int thisID = getThreadIndex();
275 edm::LogVerbatim(
"SimG4CoreApplication") <<
"RunManagerMTWorker::initializeThread " << thisID <<
" is started";
278 G4Threading::G4SetThreadId(thisID);
279 G4UImanager::GetUIpointer()->SetUpForAThread(thisID);
281 if (uitype ==
"MessageLogger") {
283 }
else if (uitype ==
"MessageLoggerThreadPrefix") {
285 }
else if (uitype ==
"FilePerThread") {
289 <<
"Invalid value of CustomUIsession.Type '" << uitype
290 <<
"', valid are MessageLogger, MessageLoggerThreadPrefix, FilePerThread";
294 G4WorkerThread::BuildGeometryAndPhysicsVector();
297 m_tls->
kernel.reset(G4WorkerRunManagerKernel::GetRunManagerKernel());
299 m_tls->
kernel = std::make_unique<G4WorkerRunManagerKernel>();
304 G4StateManager::GetStateManager()->SetExceptionHandler(
new ExceptionHandler(th));
309 G4TransportationManager* tM = G4TransportationManager::GetTransportationManager();
310 tM->SetWorldForTracking(worldPV);
322 tM->SetFieldManager(fieldManager);
323 fieldBuilder.
build(fieldManager, tM->GetPropagatorInField());
326 if (!fieldFile.empty()) {
329 edm::LogVerbatim(
"SimG4CoreApplication") <<
"RunManagerMTWorker: Dump magnetic field to file " << fieldFile;
343 <<
"RunManagerMTWorker: Sensitive Detectors are built in thread " << thisID <<
" found "
350 <<
"RunManagerMTWorker: start initialisation of PhysicsList for the thread " << thisID;
353 if (!runManagerMaster->
G4Commands().empty()) {
354 G4cout <<
"RunManagerMTWorker: Requested UI commands: " << G4endl;
357 G4UImanager::GetUIpointer()->ApplyCommand(
command);
360 G4StateManager::GetStateManager()->SetNewState(G4State_Init);
362 physicsList->InitializeWorker();
368 <<
"RunManagerMTWorker: Geant4 kernel initialization failed in thread " << thisID;
381 m_sVerbose = std::make_unique<CMSSteppingVerbose>(
sv, elim, ve, vn, vt);
385 G4StateManager::GetStateManager()->SetNewState(G4State_Idle);
390 <<
"RunManagerMTWorker::initializeThread done for the thread " << thisID <<
" " << timer;
399 G4EventManager* eventManager =
m_tls->
kernel->GetEventManager();
405 eventManager->SetUserAction(userEventAction);
409 eventManager->SetUserAction(userTrackingAction);
414 eventManager->SetUserAction(userSteppingAction);
456 int thisID = getThreadIndex();
457 edm::LogVerbatim(
"SimG4CoreApplication") <<
"RunManagerMTWorker::initializeRun " << thisID <<
" is started";
459 G4StateManager::GetStateManager()->SetNewState(G4State_GeomClosed);
466 edm::LogVerbatim(
"SimG4CoreApplication") <<
"RunManagerMTWorker::terminateRun ";
470 int thisID = getThreadIndex();
471 edm::LogVerbatim(
"SimG4CoreApplication") <<
"RunManagerMTWorker::terminateRun " << thisID <<
" is started";
500 <<
"RunManagerMTWorker::produce(): stream " << inpevt.
streamID() <<
" thread " << getThreadIndex()
501 <<
" Geant4 initialisation for this thread";
521 auto simEvent = std::make_unique<G4SimEvent>();
528 genVertex->y() / CLHEP::cm,
529 genVertex->z() / CLHEP::cm,
533 std::stringstream
ss;
534 ss <<
"RunManagerMTWorker::produce: event " << inpevt.
id().
event() <<
" with no G4PrimaryVertices \n";
539 <<
"RunManagerMTWorker::produce: start EventID=" << inpevt.
id().
event() <<
" StreamID=" << inpevt.
streamID()
540 <<
" threadIndex=" << getThreadIndex() <<
" weight=" <<
m_simEvent->
weight() <<
"; "
541 <<
m_tls->
currentEvent->GetNumberOfPrimaryVertex() <<
" vertices for Geant4; generator produced "
553 edm::LogVerbatim(
"SimG4CoreApplication") <<
"RunManagerMTWorker::produce: ended Event " << inpevt.
id().
event();
563 G4Track*
t =
m_tls->
kernel->GetEventManager()->GetTrackingManager()->GetTrack();
564 t->SetTrackStatus(fStopAndKill);
572 m_tls->
kernel->GetEventManager()->GetStackManager()->clear();
573 m_tls->
kernel->GetEventManager()->GetTrackingManager()->EventAborted();
590 G4Event* evt =
new G4Event(
evtid);
628 <<
" RunManager WARNING : error opening file <" <<
file <<
"> for magnetic field";
631 double rmax = 9000 * mm;
632 double zmax = 24000 * mm;
648 double point[4] = {0.0, 0.0, 0.0, 0.0};
649 double bfield[3] = {0.0, 0.0, 0.0};
651 fout << std::setprecision(6);
652 for (
int i = 0;
i <=
nr; ++
i) {
654 for (
int j = 0;
j <= nz; ++
j) {
658 field->GetFieldValue(
point, bfield);
659 fout <<
"R(mm)= " <<
r / mm <<
" phi(deg)= " <<
phi / degree <<
" Z(mm)= " <<
z / mm
660 <<
" Bz(tesla)= " << bfield[2] / tesla <<
" Br(tesla)= " << (bfield[0] * cosf + bfield[1] * sinf) / tesla
661 <<
" Bphi(tesla)= " << (bfield[0] * sinf - bfield[1] * cosf) / tesla << G4endl;