24 #include "GaudiKernel/IThreadInitTool.h"
33 #include "G4LorentzVector.hh"
34 #include "G4PrimaryVertex.hh"
35 #include "G4PrimaryParticle.hh"
36 #include "G4Trajectory.hh"
37 #include "G4Geantino.hh"
38 #include "G4ChargedGeantino.hh"
39 #include "G4ParticleTable.hh"
40 #include "G4StateManager.hh"
41 #include "G4TransportationManager.hh"
42 #include "G4UImanager.hh"
43 #include "G4ScoringManager.hh"
45 #include "G4SDManager.hh"
46 #include "G4VUserPhysicsList.hh"
47 #include "G4VModularPhysicsList.hh"
48 #include "G4ParallelWorldPhysics.hh"
54 static std::once_flag initializeOnceFlag;
55 static std::once_flag finalizeOnceFlag;
59 const std::string&
name,
76 m_runTimer =
new G4Timer();
77 m_eventTimer =
new G4Timer();
82 if (m_recordFlux) G4ScoringManager::GetScoringManager();
86 std::call_once(initializeOnceFlag, &iGeant4::G4TransportTool::initializeOnce,
this);
89 ATH_MSG_ERROR(
"Failure in iGeant4::G4TransportTool::initializeOnce: " <<
e.what());
90 return StatusCode::FAILURE;
101 return StatusCode::SUCCESS;
110 if(m_physListSvc.retrieve().isFailure()) {
111 throw std::runtime_error(
"Could not initialize ATLAS PhysicsListSvc!");
116 #ifdef G4MULTITHREADED
117 auto* runMgr = G4AtlasMTRunManager::GetG4AtlasMTRunManager();
118 m_physListSvc->SetPhysicsList();
119 runMgr->SetDetGeoSvc( m_detGeoSvc.typeAndName() );
120 runMgr->SetFastSimMasterTool(m_fastSimTool.typeAndName() );
121 runMgr->SetPhysListSvc( m_physListSvc.typeAndName() );
123 std::unique_ptr<G4AtlasUserWorkerThreadInitialization> workerInit =
124 std::make_unique<G4AtlasUserWorkerThreadInitialization>();
125 workerInit->SetDetGeoSvc( m_detGeoSvc.typeAndName() );
126 workerInit->SetFastSimMasterTool( m_fastSimTool.typeAndName() );
127 runMgr->SetUserInitialization( workerInit.release() );
128 std::unique_ptr<G4AtlasActionInitialization> actionInitialization =
129 std::make_unique<G4AtlasActionInitialization>(&*m_userActionSvc);
130 runMgr->SetUserInitialization(actionInitialization.release());
132 throw std::runtime_error(
"Trying to use multi-threading in non-MT build!");
137 auto* runMgr = G4AtlasRunManager::GetG4AtlasRunManager();
138 m_physListSvc->SetPhysicsList();
139 runMgr->SetRecordFlux( m_recordFlux, std::make_unique<ISFFluxRecorder>() );
140 runMgr->SetLogLevel(
int(
msg().
level()) );
141 runMgr->SetDetGeoSvc( m_detGeoSvc.typeAndName() );
142 runMgr->SetFastSimMasterTool(m_fastSimTool.typeAndName() );
143 runMgr->SetPhysListSvc(m_physListSvc.typeAndName() );
144 std::unique_ptr<G4AtlasActionInitialization> actionInitialization =
145 std::make_unique<G4AtlasActionInitialization>(&*m_userActionSvc);
146 runMgr->SetUserInitialization(actionInitialization.release());
149 G4UImanager *ui = G4UImanager::GetUIpointer();
151 if (!m_libList.empty()) {
152 ATH_MSG_INFO(
"G4AtlasAlg specific libraries requested ") ;
153 std::string temp=
"/load "+m_libList;
154 ui->ApplyCommand(temp);
157 if (!m_physList.empty()) {
158 ATH_MSG_INFO(
"requesting a specific physics list "<< m_physList) ;
159 std::string temp=
"/Physics/GetPhysicsList "+m_physList;
160 ui->ApplyCommand(temp);
163 if (!m_fieldMap.empty()) {
164 ATH_MSG_INFO(
"requesting a specific field map "<< m_fieldMap) ;
165 ATH_MSG_INFO(
"the field is initialized straight away") ;
166 std::string temp=
"/MagneticField/Select "+m_fieldMap;
167 ui->ApplyCommand(temp);
168 ui->ApplyCommand(
"/MagneticField/Initialize");
172 ATH_MSG_DEBUG(
"G4 Command: Trying at the end of initializeOnce()");
173 for (
const auto& g4command : m_g4commands) {
174 int returnCode = ui->ApplyCommand( g4command );
179 auto* rm = G4RunManager::GetRunManager();
181 throw std::runtime_error(
"Run manager retrieval has failed");
185 if(!m_useMT && rm->ConfirmBeamOnCondition()) {
186 rm->RunInitialization();
189 ATH_MSG_INFO(
"retireving the Detector Geometry Service" );
190 if(m_detGeoSvc.retrieve().isFailure()) {
191 throw std::runtime_error(
"Could not initialize ATLAS DetectorGeometrySvc!");
194 if(m_userLimitsSvc.retrieve().isFailure()) {
195 throw std::runtime_error(
"Could not initialize ATLAS UserLimitsSvc!");
198 if (m_activateParallelGeometries) {
199 G4VModularPhysicsList* thePhysicsList=
dynamic_cast<G4VModularPhysicsList*
>(m_physListSvc->GetPhysicsList());
200 if (!thePhysicsList) {
201 throw std::runtime_error(
"Failed dynamic_cast!! this is not a G4VModularPhysicsList!");
203 #if G4VERSION_NUMBER >= 1010
204 std::vector<std::string>& parallelWorldNames=m_detGeoSvc->GetParallelWorldNames();
205 for (
auto&
it: parallelWorldNames) {
206 thePhysicsList->RegisterPhysics(
new G4ParallelWorldPhysics(
it,
true));
217 ATH_MSG_VERBOSE(
"++++++++++++ ISF G4 G4TransportTool finalized ++++++++++++");
224 ATH_MSG_ERROR(
"Failure in iGeant4::G4TransportTool::finalizeOnce: " <<
e.what());
225 return StatusCode::FAILURE;
230 const float numEntriesFloat(m_nrOfEntries);
231 const float runTime=m_runTimer->GetUserElapsed()+m_runTimer->GetSystemElapsed();
232 const float avgTimePerEvent=(m_nrOfEntries>1) ? m_accumulatedEventTime/(numEntriesFloat-1.
f) : runTime;
233 const float avgTimeSqPerEvent=(m_nrOfEntries>1) ? m_accumulatedEventTimeSq/(numEntriesFloat-1.
f) : runTime*runTime;
234 const float sigma=(m_nrOfEntries>2) ? std::sqrt(std::abs(avgTimeSqPerEvent - avgTimePerEvent*avgTimePerEvent)/(numEntriesFloat-2.f)) : 0;
237 " End of run - time spent is "<<std::setprecision(4) <<
239 " Average time per event was "<<std::setprecision(4) <<
240 avgTimePerEvent <<
" +- "<< std::setprecision(4) <<
sigma<<
endmsg<<
242 "*****************************************");
245 return StatusCode::SUCCESS;
252 auto runMgr = G4RunManager::GetRunManager();
253 runMgr->RunTermination();
267 StatusCode success = this->simulateVector(ispVector, secondaries, mcEventCollection);
279 G4Event* inputEvent{};
280 if (shadowTruth && !shadowTruth->
empty()) {
281 inputEvent = m_inputConverter->ISF_to_G4Event(
particles, genEvent(mcEventCollection), shadowTruth->
back());
284 inputEvent = m_inputConverter->ISF_to_G4Event(
particles, genEvent(mcEventCollection));
288 return StatusCode::FAILURE;
298 #ifdef G4MULTITHREADED
299 auto* workerRM = G4AtlasWorkerRunManager::GetG4AtlasWorkerRunManager();
300 abort = workerRM->ProcessEvent(inputEvent);
302 ATH_MSG_ERROR(
"Trying to use multi-threading in non-MT build!");
303 return StatusCode::FAILURE;
308 abort = workerRM->ProcessEvent(inputEvent);
315 return StatusCode::FAILURE;
319 auto actionsFound = m_secondaryActions.find( std::this_thread::get_id() );
320 if ( actionsFound == m_secondaryActions.end() ) {
322 std::vector< G4UserSteppingAction* > allActions;
323 StatusCode sc = m_userActionSvc->getSecondaryActions( allActions );
324 if ( !
sc.isSuccess() ) {
325 ATH_MSG_ERROR(
"Failed to retrieve secondaries from UASvc" );
330 for ( G4UserSteppingAction*
action : allActions ) {
333 m_secondaryActions[ std::this_thread::get_id() ].push_back( castAction );
337 actionsFound = m_secondaryActions.find( std::this_thread::get_id() );
341 for (
auto*
action : actionsFound->second ) {
346 secondaries.splice(
begin(secondaries), std::move(someSecondaries) );
362 return StatusCode::SUCCESS;
370 #ifdef G4MULTITHREADED
376 if (m_useMT && G4TransportationManager::GetTransportationManager()->GetNavigatorForTracking()->GetWorldVolume() ==
nullptr)
378 ToolHandle<IThreadInitTool> ti (
"G4ThreadInitTool",
nullptr);
387 rngWrapper->
setSeed( m_randomStreamName, ctx );
388 G4Random::setTheEngine(rngWrapper->
getEngine(ctx));
390 ATH_CHECK(m_senDetTool->BeginOfAthenaEvent());
393 if (m_doTiming) m_eventTimer->Start();
396 G4SDManager::GetSDMpointer()->PrepareNewEvent();
398 return StatusCode::SUCCESS;
424 m_eventTimer->Stop();
426 const double eventTime=m_eventTimer->GetUserElapsed()+m_eventTimer->GetSystemElapsed();
427 if (m_nrOfEntries>1) {
428 m_accumulatedEventTime +=eventTime;
429 m_accumulatedEventTimeSq+=eventTime*eventTime;
432 const float numEntriesFloat(m_nrOfEntries);
433 const float avgTimePerEvent=(m_nrOfEntries>1) ? m_accumulatedEventTime/(numEntriesFloat-1.
f) : eventTime;
434 const float avgTimeSqPerEvent=(m_nrOfEntries>1) ? m_accumulatedEventTimeSq/(numEntriesFloat-1.
f) : eventTime*eventTime;
435 const float sigma=(m_nrOfEntries>2) ? std::sqrt(std::abs(avgTimeSqPerEvent - avgTimePerEvent*avgTimePerEvent)/(numEntriesFloat-2.f)) : 0;
436 ATH_MSG_INFO(
"\t Run:Event "<<ctx.eventID().run_number()<<
":"<<ctx.eventID().event_number() <<
"\t ("<<m_nrOfEntries<<
"th event for this worker) took " << std::setprecision(4) <<
437 eventTime <<
" s. New average " << std::setprecision(4) <<
438 avgTimePerEvent<<
" +- "<<std::setprecision(4) <<
sigma);
441 ATH_CHECK(m_senDetTool->EndOfAthenaEvent());
442 ATH_CHECK(m_fastSimTool->EndOfAthenaEvent());
444 return StatusCode::SUCCESS;
451 if(!mcEventCollection) {
453 if (evtStore()->contains<McEventCollection>(m_mcEventCollectionName)) {
454 if (evtStore()->
retrieve( mcEventCollection, m_mcEventCollectionName).isFailure()) {
455 ATH_MSG_ERROR(
"Unable to retrieve McEventCollection with name=" << m_mcEventCollectionName
460 ATH_MSG_WARNING(
"Fallback. Sucessfully retrieved McEventCollection with name=" << m_mcEventCollectionName);
463 else {
return nullptr; }
466 return mcEventCollection->
back();
473 case 0: {
ATH_MSG_DEBUG(
"G4 Command: " << commandString <<
" - Command Succeeded"); }
break;
474 case 100: {
ATH_MSG_ERROR(
"G4 Command: " << commandString <<
" - Command Not Found!"); }
break;
476 auto* stateManager = G4StateManager::GetStateManager();
477 ATH_MSG_DEBUG(
"G4 Command: " << commandString <<
" - Illegal Application State (" <<
478 stateManager->GetStateString(stateManager->GetCurrentState()) <<
")!");
480 case 300: {
ATH_MSG_ERROR(
"G4 Command: " << commandString <<
" - Parameter Out of Range!"); }
break;
481 case 400: {
ATH_MSG_ERROR(
"G4 Command: " << commandString <<
" - Parameter Unreadable!"); }
break;
482 case 500: {
ATH_MSG_ERROR(
"G4 Command: " << commandString <<
" - Parameter Out of Candidates!"); }
break;
483 case 600: {
ATH_MSG_ERROR(
"G4 Command: " << commandString <<
" - Alias Not Found!"); }
break;
484 default: {
ATH_MSG_ERROR(
"G4 Command: " << commandString <<
" - Unknown Status!"); }
break;