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>();
303 G4StateManager::GetStateManager()->SetExceptionHandler(
new ExceptionHandler());
308 G4TransportationManager* tM = G4TransportationManager::GetTransportationManager();
309 tM->SetWorldForTracking(worldPV);
321 tM->SetFieldManager(fieldManager);
322 fieldBuilder.
build(fieldManager, tM->GetPropagatorInField());
325 if (!fieldFile.empty()) {
328 edm::LogVerbatim(
"SimG4CoreApplication") <<
"RunManagerMTWorker: Dump magnetic field to file " << fieldFile;
342 <<
"RunManagerMTWorker: Sensitive Detectors are built in thread " << thisID <<
" found "
349 <<
"RunManagerMTWorker: start initialisation of PhysicsList for the thread " << thisID;
352 if (!runManagerMaster->
G4Commands().empty()) {
353 G4cout <<
"RunManagerMTWorker: Requested UI commands: " << G4endl;
356 G4UImanager::GetUIpointer()->ApplyCommand(
command);
359 G4StateManager::GetStateManager()->SetNewState(G4State_Init);
361 physicsList->InitializeWorker();
367 <<
"RunManagerMTWorker: Geant4 kernel initialization failed in thread " << thisID;
380 m_sVerbose = std::make_unique<CMSSteppingVerbose>(
sv, elim, ve, vn, vt);
384 G4StateManager::GetStateManager()->SetNewState(G4State_Idle);
389 <<
"RunManagerMTWorker::initializeThread done for the thread " << thisID <<
" " << timer;
398 G4EventManager* eventManager =
m_tls->
kernel->GetEventManager();
404 eventManager->SetUserAction(userEventAction);
408 eventManager->SetUserAction(userTrackingAction);
413 eventManager->SetUserAction(userSteppingAction);
455 int thisID = getThreadIndex();
456 edm::LogVerbatim(
"SimG4CoreApplication") <<
"RunManagerMTWorker::initializeRun " << thisID <<
" is started";
458 G4StateManager::GetStateManager()->SetNewState(G4State_GeomClosed);
465 edm::LogVerbatim(
"SimG4CoreApplication") <<
"RunManagerMTWorker::terminateRun ";
469 int thisID = getThreadIndex();
470 edm::LogVerbatim(
"SimG4CoreApplication") <<
"RunManagerMTWorker::terminateRun " << thisID <<
" is started";
499 <<
"RunManagerMTWorker::produce(): stream " << inpevt.
streamID() <<
" thread " << getThreadIndex()
500 <<
" Geant4 initialisation for this thread";
520 auto simEvent = std::make_unique<G4SimEvent>();
527 genVertex->y() / CLHEP::cm,
528 genVertex->z() / CLHEP::cm,
532 std::stringstream
ss;
533 ss <<
"RunManagerMTWorker::produce: event " << inpevt.
id().
event() <<
" with no G4PrimaryVertices \n";
538 <<
"RunManagerMTWorker::produce: start EventID=" << inpevt.
id().
event() <<
" StreamID=" << inpevt.
streamID()
539 <<
" threadIndex=" << getThreadIndex() <<
" weight=" <<
m_simEvent->
weight() <<
"; "
540 <<
m_tls->
currentEvent->GetNumberOfPrimaryVertex() <<
" vertices for Geant4; generator produced "
552 edm::LogVerbatim(
"SimG4CoreApplication") <<
"RunManagerMTWorker::produce: ended Event " << inpevt.
id().
event();
562 G4Track*
t =
m_tls->
kernel->GetEventManager()->GetTrackingManager()->GetTrack();
563 t->SetTrackStatus(fStopAndKill);
571 m_tls->
kernel->GetEventManager()->GetStackManager()->clear();
572 m_tls->
kernel->GetEventManager()->GetTrackingManager()->EventAborted();
589 G4Event* evt =
new G4Event(
evtid);
627 <<
" RunManager WARNING : error opening file <" <<
file <<
"> for magnetic field";
630 double rmax = 9000 * mm;
631 double zmax = 24000 * mm;
647 double point[4] = {0.0, 0.0, 0.0, 0.0};
648 double bfield[3] = {0.0, 0.0, 0.0};
650 fout << std::setprecision(6);
651 for (
int i = 0;
i <=
nr; ++
i) {
653 for (
int j = 0;
j <= nz; ++
j) {
657 field->GetFieldValue(
point, bfield);
658 fout <<
"R(mm)= " <<
r / mm <<
" phi(deg)= " <<
phi / degree <<
" Z(mm)= " <<
z / mm
659 <<
" Bz(tesla)= " << bfield[2] / tesla <<
" Br(tesla)= " << (bfield[0] * cosf + bfield[1] * sinf) / tesla
660 <<
" Bphi(tesla)= " << (bfield[0] * sinf - bfield[1] * cosf) / tesla << G4endl;