From 102e039c1905f70125f15a82daa2cf4dfc5e62d1 Mon Sep 17 00:00:00 2001
From: Benjamin Michael Wynne <b.m.wynne@ed.ac.uk>
Date: Mon, 14 Dec 2020 14:24:07 +0000
Subject: [PATCH] Added energy ordering mode for Athena vs MT comparison. Added
 optional GeoID recalculation in SimKernelMT. Now consistent

---
 .../ISF/ISF_Config/python/FlagSetters.py       | 14 ++++++++++++++
 .../ISF_Config/python/ISF_ConfigConfigDb.py    |  2 ++
 .../ISF/ISF_Config/python/ISF_MainConfig.py    | 18 ++++++++++++++++--
 .../ISF_Algorithms/src/SimKernelMT.cxx         |  9 ++++++++-
 .../ISF_Core/ISF_Algorithms/src/SimKernelMT.h  |  2 ++
 .../ISF_Services/python/ISF_ServicesConfig.py  |  5 +++++
 .../python/ISF_ServicesConfigDb.py             |  1 +
 .../python/ISF_Geant4ToolsConfig.py            |  4 ++--
 .../python/ISF_SimulationSelectorsConfig.py    |  7 +++++++
 .../test/test_MC16_G4FastCalo_ttbar_MTvsST.sh  |  6 +++---
 10 files changed, 60 insertions(+), 8 deletions(-)

diff --git a/Simulation/ISF/ISF_Config/python/FlagSetters.py b/Simulation/ISF/ISF_Config/python/FlagSetters.py
index 747c38ea6d1..1960f8b6e13 100644
--- a/Simulation/ISF/ISF_Config/python/FlagSetters.py
+++ b/Simulation/ISF/ISF_Config/python/FlagSetters.py
@@ -157,6 +157,13 @@ def configureFlagsG4FastCalo():
     simFlags.SimulationFlavour = "G4FastCalo"
     return
 
+def configureFlagsG4FastCaloEnergyOrdered():
+    configureFlagsATLFASTII()
+    ISF_Flags.ParticleBroker = "ISF_AFIIEnergyOrderedParticleBrokerSvc"
+    from G4AtlasApps.SimFlags import simFlags
+    simFlags.SimulationFlavour = "G4FastCalo"
+    return
+
 def configureFlagsG4FastCaloMT():
     configureFlagsATLFASTII()
     ISF_Flags.ParticleBroker = ""
@@ -169,6 +176,13 @@ def configureFlagsG4FastCalo_QS():
     simFlags.SimulationFlavour = "G4FastCalo_QS"
     return
 
+def configureFlagsG4FastCaloMTEnergyOrdered():
+    configureFlagsATLFASTII()
+    ISF_Flags.ParticleBroker = ""
+    from G4AtlasApps.SimFlags import simFlags
+    simFlags.SimulationFlavour = "G4FastCaloMT"
+    return
+
 def configureFlagsG4FastCaloTest():
     configureFlagsATLFASTII()
     from G4AtlasApps.SimFlags import simFlags
diff --git a/Simulation/ISF/ISF_Config/python/ISF_ConfigConfigDb.py b/Simulation/ISF/ISF_Config/python/ISF_ConfigConfigDb.py
index dad481d6a31..e501ca58ea1 100644
--- a/Simulation/ISF/ISF_Config/python/ISF_ConfigConfigDb.py
+++ b/Simulation/ISF/ISF_Config/python/ISF_ConfigConfigDb.py
@@ -47,10 +47,12 @@ addAlgorithm("ISF_Config.ISF_MainConfig.getKernel_G4HS_FastPileup",     "ISF_Ker
 addAlgorithm("ISF_Config.ISF_MainConfig.getKernel_ATLFASTIIF_IDOnly",   "ISF_Kernel_ATLFASTIIF_IDOnly")
 addAlgorithm("ISF_Config.ISF_MainConfig.getKernel_ATLFASTIIF_IDCalo",   "ISF_Kernel_ATLFASTIIF_IDCalo")
 addAlgorithm("ISF_Config.ISF_MainConfig.getKernel_G4FastCalo",          "ISF_Kernel_G4FastCalo")
+addAlgorithm("ISF_Config.ISF_MainConfig.getKernel_G4FastCaloEnergyOrdered", "ISF_Kernel_G4FastCaloEnergyOrdered")
 addAlgorithm("ISF_Config.ISF_MainConfig.getKernel_G4FastCalo_QS",       "ISF_Kernel_G4FastCalo_QS")
 addAlgorithm("ISF_Config.ISF_MainConfig.getKernel_G4FastCaloTest",      "ISF_Kernel_G4FastCaloTest")
 addAlgorithm("ISF_Config.ISF_MainConfig.getKernel_G4FastCaloDNN",          "ISF_Kernel_G4FastCaloDNN")
 addAlgorithm("ISF_Config.ISF_MainConfig.getKernel_G4FastCaloMT",         "ISF_Kernel_G4FastCaloMT")
+addAlgorithm("ISF_Config.ISF_MainConfig.getKernel_G4FastCaloMTEnergyOrdered", "ISF_Kernel_G4FastCaloMTEnergyOrdered")
 addAlgorithm("ISF_Config.ISF_MainConfig.getKernel_Fatras_newExtrapolation","ISF_Kernel_Fatras_newExtrapolation")
 addAlgorithm("ISF_Config.ISF_MainConfig.getKernel_Fatras_newExtrapolation_IDOnly","ISF_Kernel_Fatras_newExtrapolation_IDOnly")
 addAlgorithm("ISF_Config.ISF_MainConfig.getKernel_FastOnly",            "ISF_Kernel_FastOnly")
diff --git a/Simulation/ISF/ISF_Config/python/ISF_MainConfig.py b/Simulation/ISF/ISF_Config/python/ISF_MainConfig.py
index 24c76f5f576..b38ba064b62 100644
--- a/Simulation/ISF/ISF_Config/python/ISF_MainConfig.py
+++ b/Simulation/ISF/ISF_Config/python/ISF_MainConfig.py
@@ -206,6 +206,7 @@ def getKernel_GenericSimulatorMT(name="ISF_Kernel_GenericSimulatorMT", **kwargs)
     kwargs.setdefault("InputConverter", "ISF_InputConverter")
     from G4AtlasApps.SimFlags import simFlags
     kwargs.setdefault("TruthRecordService", simFlags.TruthStrategy.TruthServiceName())
+    kwargs.setdefault("AlwaysUseGeoIDSvc", False)
     #kwargs.setdefault("MemoryMonitoringTool", "ISF_MemoryMonitor")
     #kwargs.setdefault("DoCPUMonitoring", ISF_Flags.DoTimeMonitoring())
     #kwargs.setdefault("DoMemoryMonitoring", ISF_Flags.DoMemoryMonitoring())
@@ -380,12 +381,21 @@ def getKernel_G4FastCalo(name="ISF_Kernel_G4FastCalo", **kwargs):
     simFlags.SimulationFlavour = "G4FastCalo"
     return getKernel_GenericSimulator(name, **kwargs)
 
+def getKernel_G4FastCaloEnergyOrdered(name="ISF_Kernel_G4FastCaloEnergyOrdered", **kwargs):
+    kwargs.setdefault("ParticleBroker"             , 'ISF_AFIIEnergyOrderedParticleBrokerSvc')
+    return getKernel_G4FastCalo(name, **kwargs)
+
 ############## Simulator: G4FastCaloMT ###############
 def getKernel_G4FastCaloMT(name="ISF_Kernel_G4FastCaloMT", **kwargs):
     kwargs.setdefault("BeamPipeSimulationSelectors", [ 'ISF_DefaultAFIIGeant4Selector' ]            )
     kwargs.setdefault("IDSimulationSelectors"      , [ 'ISF_DefaultAFIIGeant4Selector' ]            )
     kwargs.setdefault("CaloSimulationSelectors"    , [ 'ISF_MuonAFIIGeant4Selector',
                                                        'ISF_EtaGreater5ParticleKillerSimSelector',
+                                                       'ISF_PionG4FastCaloGeant4Selector',
+                                                       'ISF_ProtonG4FastCaloGeant4Selector',
+                                                       'ISF_NeutronG4FastCaloGeant4Selector',
+                                                       'ISF_ChargedKaonG4FastCaloGeant4Selector',
+                                                       'ISF_KLongG4FastCaloGeant4Selector',
                                                        'ISF_DefaultFastCaloSimV2Selector' ] )
     kwargs.setdefault("MSSimulationSelectors"      , [ 'ISF_DefaultAFIIGeant4Selector' ]            )
     kwargs.setdefault("CavernSimulationSelectors"  , [ 'ISF_DefaultParticleKillerSelector' ]        )
@@ -394,10 +404,14 @@ def getKernel_G4FastCaloMT(name="ISF_Kernel_G4FastCaloMT", **kwargs):
                                                        'ISF_AFIIGeant4Tool'])
     kwargs.setdefault("ParticleOrderingTool"       , 'ISF_ParticleOrderingTool' )
     kwargs.setdefault('EntryLayerTool'             , 'ISF_AFIIEntryLayerToolMT')
-    from G4AtlasApps.SimFlags import simFlags #
-    simFlags.SimulationFlavour = "G4FastCalo"
+    from G4AtlasApps.SimFlags import simFlags
+    simFlags.SimulationFlavour = "G4FastCaloMT"
     return getKernel_GenericSimulatorMT(name, **kwargs)
 
+def getKernel_G4FastCaloMTEnergyOrdered(name="ISF_Kernel_G4FastCaloMTEnergyOrdered", **kwargs):
+    kwargs.setdefault("ParticleOrderingTool"       , 'ISF_EnergyParticleOrderingTool' )
+    return getKernel_G4FastCaloMT(name, **kwargs)
+
 ############## Simulator: G4FastCalo_QS ###############
 def getKernel_G4FastCalo_QS(name="ISF_Kernel_G4FastCalo_QS", **kwargs):
     kwargs.setdefault("ParticleBroker"             , 'ISF_AFIIParticleBrokerSvc'                        )
diff --git a/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernelMT.cxx b/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernelMT.cxx
index a95ea80a4f5..39f60d0d7c6 100644
--- a/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernelMT.cxx
+++ b/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernelMT.cxx
@@ -204,7 +204,9 @@ StatusCode ISF::SimKernelMT::execute() {
       particleQueue.pop();
 
       // Get the geo ID for the particle
-      m_geoIDSvc->identifyAndRegNextGeoID(curParticle);
+      if ( m_forceGeoIDSvc || !validAtlasRegion( curParticle.nextGeoID() ) ) {
+        m_geoIDSvc->identifyAndRegNextGeoID( curParticle );
+      }
 
       // Get the simulator using the GeoID
       auto& simTool = identifySimulator(curParticle);
@@ -240,7 +242,12 @@ StatusCode ISF::SimKernelMT::execute() {
     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 ) {
+
+      // Set up particle in ISF
       m_entryLayerTool->registerParticle( *secondary );
+      if ( m_forceGeoIDSvc || !validAtlasRegion( secondary->nextGeoID() ) ) {
+        m_geoIDSvc->identifyAndRegNextGeoID( *secondary );
+      }
 
       if ( m_orderingTool.empty() ) {
         // Without a defined ordering, preserve old FIFO behaviour
diff --git a/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernelMT.h b/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernelMT.h
index 61b832d9ac1..1320da5738e 100644
--- a/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernelMT.h
+++ b/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernelMT.h
@@ -96,6 +96,8 @@ private:
   SG::WriteHandleKey<TrackRecordCollection> m_muonEntryLayerKey{this, "MuonEntryLayerKey", "MuonEntryLayer", ""};
   SG::WriteHandleKey<TrackRecordCollection> m_muonExitLayerKey{this, "MuonExitLayerKey", "MuonExitLayer", ""};
 
+  /// Force geoID recalculation for each particle
+  Gaudi::Property<bool> m_forceGeoIDSvc{this, "AlwaysUseGeoIDSvc", false, "Force geoID recalculation for each particle" };
 
   /// Input converter service (from Generator->ISF particle types)
   ServiceHandle<IInputConverter> m_inputConverter{this, "InputConverter", "", "Input McEventCollection->ISFParticleContainer conversion service."};
diff --git a/Simulation/ISF/ISF_Core/ISF_Services/python/ISF_ServicesConfig.py b/Simulation/ISF/ISF_Core/ISF_Services/python/ISF_ServicesConfig.py
index 33788a8cb7c..ea5f193fc08 100644
--- a/Simulation/ISF/ISF_Core/ISF_Services/python/ISF_ServicesConfig.py
+++ b/Simulation/ISF/ISF_Core/ISF_Services/python/ISF_ServicesConfig.py
@@ -35,6 +35,11 @@ def getAFIIParticleBrokerSvc(name="ISF_AFIIParticleBrokerSvc", **kwargs):
     return getParticleBrokerSvc(name, **kwargs)
 
 
+def getAFIIEnergyOrderedParticleBrokerSvc(name="ISF_AFIIEnergyOrderedParticleBrokerSvc", **kwargs):
+    kwargs.setdefault('ParticleOrderingTool', 'ISF_EnergyParticleOrderingTool')
+    return getAFIIParticleBrokerSvc(name, **kwargs)
+
+
 def getISFEnvelopeDefSvc(name="ISF_ISFEnvelopeDefSvc", **kwargs):
     # ATLAS common envlope definitions
     kwargs.setdefault("ATLASEnvelopeDefSvc", "AtlasGeometry_EnvelopeDefSvc")
diff --git a/Simulation/ISF/ISF_Core/ISF_Services/python/ISF_ServicesConfigDb.py b/Simulation/ISF/ISF_Core/ISF_Services/python/ISF_ServicesConfigDb.py
index 7581e116c82..337493dba0b 100644
--- a/Simulation/ISF/ISF_Core/ISF_Services/python/ISF_ServicesConfigDb.py
+++ b/Simulation/ISF/ISF_Core/ISF_Services/python/ISF_ServicesConfigDb.py
@@ -15,6 +15,7 @@ addService("ISF_Services.ISF_ServicesConfig.getAFIIGeoIDSvc", "ISF_AFIIGeoIDSvc"
 addService("ISF_Services.ISF_ServicesConfig.getParticleBrokerSvc", "ISF_ParticleBrokerSvc")
 addService("ISF_Services.ISF_ServicesConfig.getParticleBrokerSvcNoOrdering", "ISF_ParticleBrokerSvcNoOrdering")
 addService("ISF_Services.ISF_ServicesConfig.getAFIIParticleBrokerSvc", "ISF_AFIIParticleBrokerSvc")
+addService("ISF_Services.ISF_ServicesConfig.getAFIIEnergyOrderedParticleBrokerSvc", "ISF_AFIIEnergyOrderedParticleBrokerSvc")
 addService("ISF_Services.ISF_ServicesConfig.getInputConverter", "ISF_InputConverter")
 addService("ISF_Services.ISF_ServicesConfig.getLongLivedInputConverter", "ISF_LongLivedInputConverter")
 addService("ISF_Services.ISF_ServicesConfig.getTruthService", "ISF_TruthService")
diff --git a/Simulation/ISF/ISF_Geant4/ISF_Geant4Tools/python/ISF_Geant4ToolsConfig.py b/Simulation/ISF/ISF_Geant4/ISF_Geant4Tools/python/ISF_Geant4ToolsConfig.py
index 77150824931..c6e444e14f1 100644
--- a/Simulation/ISF/ISF_Geant4/ISF_Geant4Tools/python/ISF_Geant4ToolsConfig.py
+++ b/Simulation/ISF/ISF_Geant4/ISF_Geant4Tools/python/ISF_Geant4ToolsConfig.py
@@ -47,7 +47,7 @@ def getPassBackG4TrackProcessorUserActionTool(name='PassBackG4TrackProcessorUser
 
 def getAFII_G4TrackProcessorUserActionTool(name='AFII_G4TrackProcessorUserActionTool', **kwargs):
     from ISF_Config.ISF_jobProperties import ISF_Flags
-    if ISF_Flags.Simulator.get_Value() in ['PassBackG4MT', 'ATLFASTIIMT', 'G4FastCaloMT']:
+    if ISF_Flags.Simulator.get_Value() in ['PassBackG4MT', 'ATLFASTIIMT', 'G4FastCaloMT', 'G4FastCaloMTEnergyOrdered']:
         kwargs.setdefault('ParticleBroker', '')
     from AthenaCommon.SystemOfUnits import MeV
     kwargs.setdefault('GeoIDSvc'                           , 'ISF_AFIIGeoIDSvc'         )
@@ -80,7 +80,7 @@ def getGeant4Tool(name="ISF_Geant4Tool", **kwargs):
     kwargs.setdefault('FastSimMasterTool', 'FastSimulationMasterTool')
     from AthenaCommon import CfgMgr
     # Workaround to keep other simulation flavours working while we migrate everything to be AthenaMT-compatible.
-    if ISF_Flags.Simulator.get_Value() in ['FullG4', 'FullG4MT', 'PassBackG4', 'PassBackG4MT', 'G4FastCalo', 'G4FastCaloMT']:
+    if ISF_Flags.Simulator.get_Value() in ['FullG4', 'FullG4MT', 'PassBackG4', 'PassBackG4MT', 'G4FastCalo', 'G4FastCaloMT', 'G4FastCaloEnergyOrdered', 'G4FastCaloMTEnergyOrdered']:
         return CfgMgr.iGeant4__G4TransportTool(name, **kwargs)
     else:
         return CfgMgr.iGeant4__G4LegacyTransportTool(name, **kwargs)
diff --git a/Simulation/ISF/ISF_SimulationSelectors/python/ISF_SimulationSelectorsConfig.py b/Simulation/ISF/ISF_SimulationSelectors/python/ISF_SimulationSelectorsConfig.py
index f60120aa5c6..5a7288fe53c 100644
--- a/Simulation/ISF/ISF_SimulationSelectors/python/ISF_SimulationSelectorsConfig.py
+++ b/Simulation/ISF/ISF_SimulationSelectors/python/ISF_SimulationSelectorsConfig.py
@@ -210,6 +210,7 @@ def getPionG4FastCaloGeant4Selector(name="ISF_PionG4FastCaloGeant4Selector", **k
     if usesSimKernelMT():
         kwargs.setdefault('Simulator', '')
     kwargs.setdefault('Simulator'       , 'ISF_AFIIGeant4SimSvc')
+    kwargs.setdefault('SimulationFlavor', SimulationFlavor.Geant4)
     return CfgMgr.ISF__KinematicSimSelector(name, **kwargs)
 
 def getPionG4FastCalo_QS_Geant4Selector(name="ISF_PionG4FastCalo_QS_Geant4Selector", **kwargs):
@@ -221,7 +222,10 @@ def getPionG4FastCalo_QS_Geant4Selector(name="ISF_PionG4FastCalo_QS_Geant4Select
 def getProtonG4FastCaloGeant4Selector(name="ISF_ProtonG4FastCaloGeant4Selector", **kwargs):
     kwargs.setdefault('MaxEkin'         , 400)
     kwargs.setdefault('ParticlePDG'     , 2212)
+    if usesSimKernelMT():
+        kwargs.setdefault('Simulator', '')
     kwargs.setdefault('Simulator'       , 'ISF_AFIIGeant4SimSvc')
+    kwargs.setdefault('SimulationFlavor', SimulationFlavor.Geant4)
     return CfgMgr.ISF__KinematicSimSelector(name, **kwargs)
 
 def getProtonG4FastCalo_QS_Geant4Selector(name="ISF_ProtonG4FastCalo_QS_Geant4Selector", **kwargs):
@@ -236,6 +240,7 @@ def getNeutronG4FastCaloGeant4Selector(name="ISF_NeutronG4FastCaloGeant4Selector
     if usesSimKernelMT():
         kwargs.setdefault('Simulator', '')
     kwargs.setdefault('Simulator'       , 'ISF_AFIIGeant4SimSvc')
+    kwargs.setdefault('SimulationFlavor', SimulationFlavor.Geant4)
     return CfgMgr.ISF__KinematicSimSelector(name, **kwargs)
 
 def getNeutronG4FastCalo_QS_Geant4Selector(name="ISF_NeutronG4FastCalo_QS_Geant4Selector", **kwargs):
@@ -250,6 +255,7 @@ def getChargedKaonG4FastCaloGeant4Selector(name="ISF_ChargedKaonG4FastCaloGeant4
     if usesSimKernelMT():
         kwargs.setdefault('Simulator', '')
     kwargs.setdefault('Simulator'       , 'ISF_AFIIGeant4SimSvc')
+    kwargs.setdefault('SimulationFlavor', SimulationFlavor.Geant4)
     return CfgMgr.ISF__KinematicSimSelector(name, **kwargs)
 
 def getChargedKaonG4FastCalo_QS_Geant4Selector(name="ISF_ChargedKaonG4FastCalo_QS_Geant4Selector", **kwargs):
@@ -264,6 +270,7 @@ def getKLongG4FastCaloGeant4Selector(name="ISF_KLongG4FastCaloGeant4Selector", *
     if usesSimKernelMT():
         kwargs.setdefault('Simulator', '')
     kwargs.setdefault('Simulator'       , 'ISF_AFIIGeant4SimSvc')
+    kwargs.setdefault('SimulationFlavor', SimulationFlavor.Geant4)
     return CfgMgr.ISF__KinematicSimSelector(name, **kwargs)
 
 def getKLongG4FastCalo_QS_Geant4Selector(name="ISF_KLongG4FastCalo_QS_Geant4Selector", **kwargs):
diff --git a/Simulation/Tests/ISF_ValidationMT/test/test_MC16_G4FastCalo_ttbar_MTvsST.sh b/Simulation/Tests/ISF_ValidationMT/test/test_MC16_G4FastCalo_ttbar_MTvsST.sh
index 4841cabf7c7..ee46c1c0e85 100755
--- a/Simulation/Tests/ISF_ValidationMT/test/test_MC16_G4FastCalo_ttbar_MTvsST.sh
+++ b/Simulation/Tests/ISF_ValidationMT/test/test_MC16_G4FastCalo_ttbar_MTvsST.sh
@@ -20,7 +20,7 @@ Sim_tf.py \
 --DataRunNumber '284500' \
 --physicsList 'FTFP_BERT_ATL' \
 --truthStrategy 'MC15aPlus' \
---simulator 'G4FastCaloMT' \
+--simulator 'G4FastCaloMTEnergyOrdered' \
 --postInclude 'default:PyJobTransforms/UseFrontier.py' \
 --preInclude 'EVNTtoHITS:SimulationJobOptions/preInclude.BeamPipeKill.py' \
 --preExec 'EVNTtoHITS:simFlags.TightMuonStepping=True' #\
@@ -46,7 +46,7 @@ then
   --DataRunNumber '284500' \
   --physicsList 'FTFP_BERT_ATL' \
   --truthStrategy 'MC15aPlus' \
-  --simulator 'G4FastCaloMT' \
+  --simulator 'G4FastCaloMTEnergyOrdered' \
   --postInclude 'default:PyJobTransforms/UseFrontier.py' \
   --preInclude 'EVNTtoHITS:SimulationJobOptions/preInclude.BeamPipeKill.py' \
   --preExec 'EVNTtoHITS:simFlags.TightMuonStepping=True' #\
@@ -71,7 +71,7 @@ then
   --DataRunNumber '284500' \
   --physicsList 'FTFP_BERT_ATL' \
   --truthStrategy 'MC15aPlus' \
-  --simulator 'G4FastCalo' \
+  --simulator 'G4FastCaloEnergyOrdered' \
   --postInclude 'default:PyJobTransforms/UseFrontier.py' \
   --preInclude 'EVNTtoHITS:SimulationJobOptions/preInclude.BeamPipeKill.py' \
   --preExec 'EVNTtoHITS:simFlags.TightMuonStepping=True' #\
-- 
GitLab