17 #include "Gaudi/Property.h"
41 m_inputHardScatterEvgen(),
43 m_outputHardScatterTruth(),
44 m_outputPileupTruth(),
45 m_inputConverter(
"",
name),
46 m_particleBroker(
"ISF_ParticleBroker",
name),
47 m_truthRecordSvc(
"ISF_TruthRecordSvc",
name),
48 m_qspatcher(
"",
name),
50 m_memMon(
"MemMonitoringTool"),
61 m_maxParticleVectorSize(10240)
65 "Input Hard Scatter EVGEN collection.");
68 "Input Pileup EVGEN collection.");
71 "Output Hard Scatter Truth collection.");
74 "Output Pileup Truth collection.");
77 "Input McEventCollection->ISFParticleContainer conversion service.");
110 ATH_MSG_VERBOSE (
"--------------------------------------------------------" );
117 ATH_MSG_INFO(
"- MemoryMonitoring : " << m_memMon.typeAndName() );
119 m_memMon->recordCurrent(
"at beginning of SimKernel initialize()");
134 ATH_CHECK ( m_particleBroker.retrieve() );
135 ATH_MSG_INFO(
"- ParticleBroker : " << m_particleBroker.typeAndName() );
138 ATH_CHECK ( m_truthRecordSvc.retrieve() );
139 ATH_MSG_INFO(
"- TruthRecordSvc : " << m_truthRecordSvc.typeAndName() );
144 ATH_CHECK ( initSimSvcs(m_simSelectors[geoID]) );
147 ATH_CHECK( m_inputConverter.retrieve() );
148 if ( not m_truthPreselectionTool.empty() ) {
149 ATH_CHECK(m_truthPreselectionTool.retrieve());
152 if(!m_qspatcher.empty()) {
158 ATH_MSG_INFO(
"The following Event Filters are defined:");
162 m_simSvcs.resize( m_numSimSvcs);
163 m_simSvcNames.resize( m_numSimSvcs);
165 ATH_MSG_INFO (
"The following SimulationSvc are registered to ISF:");
167 ATH_MSG_INFO (
"ID: " <<
id <<
"\t Name: '" << m_simSvcNames[
id]
176 ATH_MSG_INFO(
"The following routing chains are defined:");
179 <<
" (GeoID=" << geoID <<
"): \t" << m_simSelectors[geoID]);
183 if (m_doMemMon) m_memMon->recordCurrent(
"at end of ISF SimKernel initialize()");
185 ATH_CHECK ( m_inputHardScatterEvgen.initialize() );
186 ATH_CHECK ( m_inputPileupEvgen.initialize( !m_inputPileupEvgen.key().empty() ) );
187 ATH_CHECK ( m_outputHardScatterTruth.initialize() );
188 ATH_CHECK ( m_outputPileupTruth.initialize( !m_outputPileupTruth.key().empty() ) );
191 return StatusCode::SUCCESS;
200 if (m_doMemMon) m_memMon->recordCurrent(
"at beginning of ISF SimKernel finalize()");
203 ATH_MSG_INFO(
" Number of particles handled by the ISF SimKernel: " << m_numParticles );
205 ATH_MSG_INFO(
" ========================= ISF Timing Stats =========================");
208 ATH_MSG_INFO(
"Breakdown of simulation loop by SimulatorID:");
213 m_benchSimID->getData(simID,
count, time_ms);
216 <<m_simSvcNames[simID]<<
" (id="<<simID<<
")"
217 <<
"\t\tn="<<
count<<
"\t\tt=" <<time_ms<<
" ms\t\tt/n="<<time_ms/
count<<
" ms"
218 <<std::setprecision(-1) );
267 ATH_MSG_INFO(
" ====================== ISF Memory Usage Stats =======================");
268 m_memMon->dumpSummary(
"end of ISF event");
271 ATH_MSG_INFO(
" =====================================================================");
273 return StatusCode::SUCCESS;
280 if ( simSelectorTools.retrieve().isFailure() ) {
281 ATH_MSG_FATAL(
"Could not retrieve SimulatorSelector Tool Array. Abort." );
282 return StatusCode::FAILURE;
288 for ( ; fSimSelectorIter != fSimSelectorIterEnd; ++fSimSelectorIter ) {
293 if ( (*curSimulator).retrieve().isFailure() ){
294 ATH_MSG_FATAL(
"Could not retrieve SimulatorSelector Tool. Abort." );
295 return StatusCode::FAILURE;
297 ATH_MSG_INFO(
"- SimulationSelector : " << fSimSelectorIter->typeAndName() );
300 if ( (*curSimulator)->setParticleBroker( &*m_particleBroker).isFailure() ){
301 ATH_MSG_FATAL(
"Unable to register ParticleService to SimulationService "
303 return StatusCode::FAILURE;
307 SimSvcID curID = (*curSimulator)->simSvcID();
311 (*curSimulator)->assignSimSvcID( m_numSimSvcs);
313 m_simSvcs[m_numSimSvcs] = (&**curSimulator);
314 m_simSvcNames[m_numSimSvcs] = (*curSimulator)->simSvcDescriptor();
316 <<
" to simulator '" << m_simSvcNames[m_numSimSvcs]
325 return StatusCode::SUCCESS;
335 if ( m_doMemMon && (m_numISFEvents==0) ) {
336 m_memMon->dumpCurrent(
"before 1st event",
false );
337 m_memMon->recordCurrent(
"before 1st event");
340 auto hitCollections = std::make_shared<HitCollectionMap>();
345 std::unique_ptr<McEventCollection> shadowTruth{};
346 std::unique_ptr<McEventCollection> shadowPileUpTruth{};
347 ATH_CHECK( prepareInput(m_inputHardScatterEvgen, m_outputHardScatterTruth, shadowTruth, simParticles) );
349 if (!m_inputPileupEvgen.key().empty()) {
350 ATH_CHECK( prepareInput(m_inputPileupEvgen, m_outputPileupTruth, shadowPileUpTruth, simParticles) );
355 ATH_CHECK ( m_particleBroker->initializeEvent( std::move(simParticles) ) );
357 const int largestGeneratedParticleBC = (m_outputHardScatterTruth->empty()) ?
HepMC::UNDEFINED_ID
359 const int largestGeneratedVertexBC = (m_outputHardScatterTruth->empty()) ?
HepMC::UNDEFINED_ID
362 ATH_CHECK( m_truthRecordSvc->initializeTruthCollection(largestGeneratedParticleBC, largestGeneratedVertexBC) );
371 for ( ; fSimSvcIter != fSimSvcIterEnd; ++fSimSvcIter ){
377 if (
auto* curSimSvcG4 =
380 return curSimSvcG4->setupEvent(*hitCollections);
402 unsigned int loopCounter{0};
403 ATH_MSG_DEBUG(
"Starting simulation loop, initial particle stack size: " << m_particleBroker->numParticles());
404 while ( m_particleBroker->numParticles() ) {
407 ATH_MSG_VERBOSE(
"Queue starts with " << m_particleBroker->numParticles() <<
" particles.");
410 const unsigned int numParticlesLeftInBroker = m_particleBroker->numParticles();
414 if (numParticles==0)
break;
417 m_numParticles += numParticles;
424 ATH_MSG_DEBUG (
"Took " << numParticles <<
" particles from queue (remaining: " << m_particleBroker->numParticles() <<
")" );
425 ATH_MSG_VERBOSE(
" -> All particles will be sent to '" << m_simSvcNames[simID] <<
"' simulator (SimSvcID=" << simID <<
")" );
428 if (loopCounter>100 && numParticles<3) {
430 ATH_MSG_INFO(
"Selected " << numParticles <<
" particles to be processed by " << m_simSvcNames[simID]);
439 if (
particle->nextSimID() != simID ) {
440 ATH_MSG_WARNING(
"Particle with SimID " <<
particle->nextSimID() <<
" found in vector with expected ID " << simID );
456 if (
auto* curSimSvcG4 =
460 ->simulateVector(
particles, m_outputHardScatterTruth.ptr(),
461 hitCollections, shadowTruth.get())
464 << m_simSvcNames[simID]);
466 }
else if (m_simSvcs[simID]
467 ->simulateVector(
particles, m_outputHardScatterTruth.ptr(),
470 ATH_MSG_WARNING(
"Simulation of particles failed in Simulator: " << m_simSvcNames[simID]);
472 ATH_MSG_VERBOSE(m_simSvcNames[simID] <<
" returned " << m_particleBroker->numParticles()-numParticlesLeftInBroker <<
" new particles to be added to the queue." );
476 ATH_MSG_VERBOSE(
"Final status: queue contains " << m_particleBroker->numParticles() <<
" particles.");
483 if ( m_particleBroker->finalizeEvent().isFailure()) {
484 ATH_MSG_WARNING(
"ParticleBroker returned with an error in event finalization." );
490 for ( ; fSimSvcIter != fSimSvcIterEnd; ++fSimSvcIter ){
496 if (
auto* curSimSvcG4 =
499 return curSimSvcG4->releaseEvent(*hitCollections);
516 if ( m_truthRecordSvc->releaseEvent().isFailure() ){
517 ATH_MSG_FATAL(
"Event finalize failed for TruthService. Abort." );
518 return StatusCode::FAILURE;
522 if(!m_qspatcher.empty()) {
523 for (HepMC::GenEvent* currentGenEvent : *m_outputHardScatterTruth ) {
524 ATH_CHECK(m_qspatcher->removeWorkaround(*currentGenEvent));
531 while (eventFilter != endOfEventFilters) {
532 if (!((**eventFilter).eventPassesFilter())) {
533 setFilterPassed(
false);
534 ATH_MSG_INFO(
"This event failed the " << (**eventFilter).name() <<
" Filter. Therefore it will not be recorded.");
546 std::string
descr(
"after event " + evtStr);
547 m_memMon->dumpCurrent(
descr.c_str(),
true);
553 if ( !(m_numISFEvents%m_memUsageEvts) ) m_memMon->recordCurrent(
descr.c_str() );
554 else if ( m_numISFEvents==1) m_memMon->recordCurrent(
"after 1st event");
555 else if ( m_numISFEvents==2) m_memMon->recordCurrent(
"after 2nd event");
556 else if ( m_numISFEvents==10) m_memMon->recordCurrent(
"after 10th event");
557 else if ( m_numISFEvents==100) m_memMon->recordCurrent(
"after 100th event");
560 return StatusCode::SUCCESS;
568 std::unique_ptr<McEventCollection>& shadowTruth,
572 ATH_MSG_FATAL(
"Unable to read input GenEvent collection '" << inputTruth.
key() <<
"'");
573 return StatusCode::FAILURE;
576 if (m_useShadowEvent) {
577 outputTruth = std::make_unique<McEventCollection>();
579 shadowTruth = std::make_unique<McEventCollection>(*inputTruth);
580 for (HepMC::GenEvent* currentGenEvent : *shadowTruth ) {
582 if ( not m_qspatcher.empty() ) {
583 ATH_CHECK(m_qspatcher->applyWorkaround(*currentGenEvent));
586 std::unique_ptr<HepMC::GenEvent> outputEvent = m_truthPreselectionTool->filterGenEvent(*currentGenEvent);
587 outputTruth->
push_back(outputEvent.release());
592 outputTruth = std::make_unique<McEventCollection>(*inputTruth);
595 if(!m_qspatcher.empty()) {
596 for (HepMC::GenEvent* currentGenEvent : *outputTruth ) {
597 ATH_CHECK(m_qspatcher->applyWorkaround(*currentGenEvent));
601 ATH_CHECK( m_inputConverter->convert(*outputTruth, simParticles) );
603 return StatusCode::SUCCESS;