From 87bec75110ff86ec31552a6eb3f1fe4faa9b0c6e Mon Sep 17 00:00:00 2001
From: John Chapman <jchapman@cern.ch>
Date: Fri, 7 Aug 2020 18:17:57 +0200
Subject: [PATCH] Output of PassBackG4 and PassBackG4MT agrees

---
 .../ISF_Core/ISF_Algorithms/src/SimKernel.cxx | 11 +++++++--
 .../ISF_Algorithms/src/SimKernelMT.cxx        | 24 ++++++++++++-------
 .../ISF_Core/ISF_Algorithms/src/SimKernelMT.h |  2 ++
 .../src/ParticleBrokerDynamicOnReadIn.cxx     | 17 ++++++++-----
 4 files changed, 38 insertions(+), 16 deletions(-)

diff --git a/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernel.cxx b/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernel.cxx
index 02bcb6db259..51210782d11 100644
--- a/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernel.cxx
+++ b/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernel.cxx
@@ -372,10 +372,15 @@ StatusCode ISF::SimKernel::execute()
 
   // -----------------------------------------------------------------------------------------------
   // Step 3: ISimulation KERNEL : loop over particle stack, until empty
+  unsigned int loopCounter{0};
   ATH_MSG_DEBUG( "Starting simulation loop, initial particle stack size: " << m_particleBroker->numParticles());
-  while ( true ) {
+  while ( m_particleBroker->numParticles() ) {
+    ++loopCounter;
+    ATH_MSG_VERBOSE("Main Loop pass no. " << loopCounter);
+    ATH_MSG_VERBOSE("Queue starts with " << m_particleBroker->numParticles() << " particles.");
     // get next vector of particles for simulation
     const ISF::ConstISFParticleVector &particles = m_particleBroker->popVector(m_maxParticleVectorSize);
+    const unsigned int numParticlesLeftInBroker = m_particleBroker->numParticles();
     int numParticles = particles.size();
     // particle vector empty -> end simulation
     if (numParticles==0) break;
@@ -409,13 +414,15 @@ StatusCode ISF::SimKernel::execute()
       // NB Passing only the hard-scatter McEventCollection is not
       // correct if Geant4 simulation were to be used for pile-up Hits
       // in Fast Chain.
+      ATH_MSG_VERBOSE("Selected " << particles.size() << " particles to be processed by " <<  m_simSvcNames[simID]);
       if (m_simSvcs[simID]->simulateVector(particles, m_outputHardScatterTruth.ptr()).isFailure()) {
         ATH_MSG_WARNING( "Simulation of particles failed in Simulator: " << m_simSvcNames[simID]);
       }
+      ATH_MSG_VERBOSE(m_simSvcNames[simID] << " returned " << m_particleBroker->numParticles()-numParticlesLeftInBroker << " new particles to be added to the queue." );
     }
 
   }
-  ATH_MSG_VERBOSE( "Ending simulation loop, no more particles in the stack" );
+  ATH_MSG_VERBOSE("Final status: queue contains " << m_particleBroker->numParticles() << " particles.");
   // -----------------------------------------------------------------------------------------------
 
 
diff --git a/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernelMT.cxx b/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernelMT.cxx
index 58697b51e49..01aaa00efb1 100644
--- a/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernelMT.cxx
+++ b/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernelMT.cxx
@@ -18,6 +18,7 @@
 
 // STL
 #include <queue>
+#include <utility>
 
 
 ISF::SimKernelMT::SimKernelMT( const std::string& name, ISvcLocator* pSvcLocator ) :
@@ -30,6 +31,8 @@ ISF::SimKernelMT::SimKernelMT( const std::string& name, ISvcLocator* pSvcLocator
     declareProperty("CaloSimulationSelectors", m_simSelectors[AtlasDetDescr::fAtlasCalo] );
     declareProperty("MSSimulationSelectors", m_simSelectors[AtlasDetDescr::fAtlasMS] );
     declareProperty("CavernSimulationSelectors", m_simSelectors[AtlasDetDescr::fAtlasCavern] );
+    // tuning parameters
+    declareProperty("MaximumParticleVectorSize"  , m_maxParticleVectorSize             );
 }
 
 
@@ -183,13 +186,17 @@ StatusCode ISF::SimKernelMT::execute() {
     particleQueue.push( particle );
   }
 
+  unsigned int loopCounter{0};
   // loop until there are no more particles to simulate
   ISF::ConstISFParticleVector particles{};
   const ISimulatorTool* lastSimulator{};
   ISFParticleContainer newSecondaries{};
   while ( particleQueue.size() ) {
-
+    ++loopCounter;
+    ATH_MSG_VERBOSE("Main Loop pass no. " << loopCounter);
+    ATH_MSG_VERBOSE("Queue starts with " << particleQueue.size() << " particles.");
     // Create a vector of particles with the same simulator
+    ISFParticleOrderedQueue tempQueue;
     while ( particleQueue.size() ) {
       auto particlePtr = particleQueue.top();
       ISFParticle& curParticle( *particlePtr );
@@ -207,19 +214,19 @@ StatusCode ISF::SimKernelMT::execute() {
         particles.push_back(particlePtr);
         lastSimulator=&simTool;
       }
-      else if (&simTool==lastSimulator) {
-        particles.push_back(particlePtr);
+      else if (&simTool!=lastSimulator || particles.size() >= m_maxParticleVectorSize ) {
+        // Change of simulator, end the current vector
+        tempQueue.push(particlePtr);
       }
       else {
-        // Change of simulator, end the current vector
-        particleQueue.push(particlePtr);
-        break;
+        particles.push_back(particlePtr);
       }
     }
-
+    particleQueue = std::move(tempQueue);
+    ATH_MSG_VERBOSE("Selected " << particles.size() << " particles to be processed by " << lastSimulator->name());
     // Run the simulation
     ATH_CHECK( lastSimulator->simulateVector( particles, newSecondaries, outputTruth.ptr() ) );
-
+    ATH_MSG_VERBOSE(lastSimulator->name() << " returned " << newSecondaries.size() << " new particles to be added to the queue." );
     // Register returned particles with the entry layer tool, set their order and enqueue them
     for ( auto* secondary : newSecondaries ) {
       m_entryLayerTool->registerParticle( *secondary );
@@ -242,6 +249,7 @@ StatusCode ISF::SimKernelMT::execute() {
     }
     particles.clear();
   }
+  ATH_MSG_VERBOSE("Final status: queue contains " << particleQueue.size() << " particles.");
 
   // Release the event from all simulators (TODO: make the tools do this)
   for (auto& curSimTool: m_simulationTools) {
diff --git a/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernelMT.h b/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernelMT.h
index ad492636dd1..61b832d9ac1 100644
--- a/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernelMT.h
+++ b/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernelMT.h
@@ -127,6 +127,8 @@ private:
   /// Map of the simulation flavours used in this job to the corresponding Simulation Services
   std::map<ISF::SimulationFlavor, ISimulatorTool*> m_simToolMap;
 
+  /// Number of particles simultaneously sent to simulator
+  size_t m_maxParticleVectorSize{10240};
 };
 
 } // namespace ISF
diff --git a/Simulation/ISF/ISF_Core/ISF_Services/src/ParticleBrokerDynamicOnReadIn.cxx b/Simulation/ISF/ISF_Core/ISF_Services/src/ParticleBrokerDynamicOnReadIn.cxx
index 652fe01d7b2..33b0d73167d 100644
--- a/Simulation/ISF/ISF_Core/ISF_Services/src/ParticleBrokerDynamicOnReadIn.cxx
+++ b/Simulation/ISF/ISF_Core/ISF_Services/src/ParticleBrokerDynamicOnReadIn.cxx
@@ -30,6 +30,8 @@
 // ROOT includes
 #include "TTree.h"
 
+#include <utility>
+
 // C include
 #include <assert.h>
 
@@ -485,7 +487,7 @@ const ISF::ConstISFParticleVector& ISF::ParticleBrokerDynamicOnReadIn::popVector
   if ( m_particles.size() ) {
 
     SimSvcID returnID = m_particles.top()->nextSimID();
-
+    ISFParticleOrderedQueue tempQueue;
     // loop as long as we have particles in the m_particles queue
     do {
       // get the next particle from the ordered queue
@@ -494,14 +496,17 @@ const ISF::ConstISFParticleVector& ISF::ParticleBrokerDynamicOnReadIn::popVector
 
       // if this particle has a different SimID, or the maximum size of the return vector is reached
       //   -> don't add any more particles to the m_popParticles std::vector
-      if ( curID != returnID || m_popParticles.size() >= maxVectorSize ) break;
-
-      // add this particle to the, later returned, m_popParticles std::vector
-      m_popParticles.push_back( curParticle );
+      if ( curID != returnID || m_popParticles.size() >= maxVectorSize ) {
+        tempQueue.push(m_particles.top()); //break;
+      }
+      else {
+        // add this particle to the, later returned, m_popParticles std::vector
+        m_popParticles.push_back( curParticle );
+      }
       // remove this particle from the ordered queue
       m_particles.pop();
     } while ( m_particles.size() ) ;
-
+    m_particles = std::move(tempQueue);
   }
   // return the popParticles vector
   return m_popParticles;
-- 
GitLab