48 ATH_CHECK( m_simulationTools.retrieve() );
49 for (
auto& curSimTool : m_simulationTools )
53 const auto flavor = curSimTool->simFlavor();
54 auto itr = m_simToolMap.find(flavor);
55 if (itr != m_simToolMap.end() )
57 ATH_MSG_FATAL(
"Two ISimulatorTool instances (" << itr->second->name() <<
"," << curSimTool->name() <<
") with the same flavor in this job!\n Check your configuration!");
58 return StatusCode::FAILURE;
61 m_simToolMap[flavor] = &*curSimTool;
63 m_particleKillerTool = &*curSimTool;
68 if (!m_particleKillerTool) {
69 ATH_MSG_FATAL(
"No fallback ParticleKiller Simulator Tool provided in SimulationTools, the job will bail out now.");
70 return StatusCode::FAILURE;
73 ATH_MSG_INFO(
"The following Simulators will be used in this job: \t" << m_simulationTools);
75 for (
auto& selectorsToolHandleArray: m_simSelectors )
77 ATH_CHECK( selectorsToolHandleArray.retrieve() );
81 ATH_MSG_INFO(
"The following routing chains are defined:" );
84 auto& localSelectors = m_simSelectors[geoID];
87 for (
auto&
selector : localSelectors )
89 const auto flavor =
selector->simFlavor();
90 auto itr = m_simToolMap.find(flavor);
91 if (itr == m_simToolMap.end() )
94 for (
auto&
entry : m_simToolMap )
98 ATH_MSG_FATAL(
"No SimulationTool with flavor " << flavor <<
" expected by " <<
selector->name() <<
" found in this job!\n Check your configuration!" );
99 return StatusCode::FAILURE;
104 ATH_CHECK( m_entryLayerTool.retrieve() );
106 if ( not m_orderingTool.empty() ) {
110 ATH_CHECK( m_inputEvgenKey.initialize() );
111 ATH_CHECK( m_outputTruthKey.initialize() );
113 ATH_CHECK( m_caloEntryLayerKey.initialize() );
114 ATH_CHECK( m_muonEntryLayerKey.initialize() );
115 ATH_CHECK( m_muonExitLayerKey.initialize() );
117 ATH_CHECK( m_inputConverter.retrieve() );
118 if ( not m_truthPreselectionTool.empty() ) {
119 ATH_CHECK(m_truthPreselectionTool.retrieve());
122 ATH_CHECK ( m_truthRecordSvc.retrieve() );
124 if ( not m_qspatcher.empty() ) {
130 return StatusCode::SUCCESS;
136 const EventContext& ctx = Gaudi::Hive::currentContext();
137 auto hitCollections = std::make_shared<HitCollectionMap>();
139 for (
auto& curSimTool: m_simulationTools) {
143 ATH_CHECK(g4sim->setupEvent(ctx, *hitCollections));
147 ATH_MSG_DEBUG(
"Event setup done for " << curSimTool->name() );
153 ATH_MSG_FATAL(
"Unable to read input GenEvent collection '" << inputEvgen.
key() <<
"'");
154 return StatusCode::FAILURE;
159 std::unique_ptr<McEventCollection> shadowTruth{};
160 if (m_useShadowEvent) {
161 outputTruth = std::make_unique<McEventCollection>();
163 shadowTruth = std::make_unique<McEventCollection>(*inputEvgen);
164 for (HepMC::GenEvent* currentGenEvent : *shadowTruth ) {
166 if ( not m_qspatcher.empty() ) {
167 ATH_CHECK(m_qspatcher->applyWorkaround(*currentGenEvent));
170 std::unique_ptr<HepMC::GenEvent> outputEvent = m_truthPreselectionTool->filterGenEvent(*currentGenEvent);
171 outputTruth->
push_back(outputEvent.release());
176 outputTruth = std::make_unique<McEventCollection>(*inputEvgen);
178 if ( not m_qspatcher.empty() ) {
179 for (HepMC::GenEvent* currentGenEvent : *outputTruth ) {
180 ATH_CHECK(m_qspatcher->applyWorkaround(*currentGenEvent));
190 ATH_CHECK( m_truthRecordSvc->initializeTruthCollection(largestGeneratedParticleBC, largestGeneratedVertexBC) );
194 caloEntryLayer = std::make_unique<TrackRecordCollection>(caloEntryLayer.
name());
197 muonEntryLayer = std::make_unique<TrackRecordCollection>(muonEntryLayer.
name());
200 muonExitLayer = std::make_unique<TrackRecordCollection>(muonExitLayer.
name());
205 ATH_CHECK( m_inputConverter->convert(*outputTruth, simParticles) );
209 for (
auto&
particle : simParticles ) {
211 if ( m_orderingTool.empty() ) {
213 particle->setOrder( -particleQueue.size() );
215 m_orderingTool->setOrder( *
particle );
221 unsigned int loopCounter{0};
226 while ( particleQueue.size() ) {
229 ATH_MSG_VERBOSE(
"Queue starts with " << particleQueue.size() <<
" particles.");
232 while ( particleQueue.size() ) {
233 auto particlePtr = particleQueue.top();
239 m_geoIDSvc->identifyAndRegNextGeoID( curParticle );
243 auto& simTool = identifySimulator(curParticle);
249 lastSimulator=&simTool;
251 else if (&simTool!=lastSimulator ||
particles.size() >= m_maxParticleVectorSize ) {
253 tempQueue.push(particlePtr);
259 particleQueue = std::move(tempQueue);
261 if (loopCounter>100 &&
particles.size()<3) {
263 ATH_MSG_INFO(
"Selected " <<
particles.size() <<
" particles to be processed by " << lastSimulator->name());
274 outputTruth.
ptr(), hitCollections,
282 ATH_MSG_VERBOSE(lastSimulator->name() <<
" returned " << newSecondaries.size() <<
" new particles to be added to the queue." );
284 for (
auto* secondary : newSecondaries ) {
287 m_entryLayerTool->registerParticle( *secondary );
289 m_geoIDSvc->identifyAndRegNextGeoID( *secondary );
292 if ( m_orderingTool.empty() ) {
294 secondary->setOrder( -particleQueue.size() );
296 m_orderingTool->setOrder( *secondary );
299 particleQueue.push( secondary );
301 newSecondaries.clear();
309 ATH_MSG_VERBOSE(
"Final status: queue contains " << particleQueue.size() <<
" particles.");
312 for (
auto& curSimTool: m_simulationTools) {
316 ATH_CHECK(g4sim->releaseEvent(ctx, *hitCollections));
318 ATH_CHECK(curSimTool->releaseEvent(ctx));
320 ATH_MSG_DEBUG(
"releaseEvent() completed for " << curSimTool->name() );
325 if(!m_qspatcher.empty()) {
326 for (HepMC::GenEvent* currentGenEvent : *outputTruth ) {
327 ATH_CHECK(m_qspatcher->removeWorkaround(*currentGenEvent));
331 return StatusCode::SUCCESS;
336 return StatusCode::SUCCESS;
344 auto& localSelectors = m_simSelectors[geoID];
345 for (
auto&
selector: localSelectors) {
348 return *m_simToolMap.at(
selector->simFlavor());
353 <<
" Will send it to " << m_particleKillerTool->name());
354 return *m_particleKillerTool;