From 13c1123e525cf7093734b511997e3fd5fd1688d0 Mon Sep 17 00:00:00 2001
From: John Derek Chapman <chapman@hep.phy.cam.ac.uk>
Date: Tue, 29 Nov 2016 22:15:46 +0100
Subject: [PATCH] src/DetectorGeometryBase.cxx (SetRotationAndOffset): ensure
 that additional translations are added to any existing ones rather than
 overwriting them. ATLASSIM-3001. Tagging: G4AtlasTools-00-02-23-02
 (G4AtlasTools-00-02-23-02)

2016-11-29  John Chapman  <John.Chapman@cern.ch>
	* Tagging: G4AtlasTools-00-02-23-02
	* Branch for Muon Envelope updates in 20.3.X-VAL.
	* Tagging: G4AtlasTools-00-02-23-01

2016-06-17  John Chapman  <John.Chapman@cern.ch>

	add hook for HGTDSensorSD. ATLASSIM-2789.
	* Tagging: G4AtlasTools-00-02-23

2016-06-16  Zach Marshall <ZLMarshall@lbl.gov>
	* Adding more overrides to fix a bunch more clang warnings
	* Tagging: G4AtlasTools-00-02-22

2016-06-08  Zach Marshall <ZLMarshall@lbl.gov>

	* TightMuonSteppingFieldManager: Had min and max upside down
	* Tagging: G4AtlasTools-00-02-21

2016-06-04  Zach Marshall <ZLMarshall@lbl.gov>
...
(Long ChangeLog diff - truncated)
---
 .../G4AtlasTools/DetectorFieldManagerTool.h   |  3 +
 .../G4AtlasTools/G4AtlasTools/EnvelopeTool.h  |  2 +-
 .../G4AtlasTools/FastSimulationBase.h         |  2 +-
 .../G4AtlasTools/GlobalFieldManagerTool.h     |  7 +++
 .../G4AtlasTools/SensitiveDetectorBase.h      |  2 +-
 .../G4AtlasTools/UserActionBase.h             |  4 +-
 .../G4AtlasTools/python/G4AtlasToolsConfig.py |  5 +-
 .../python/G4AtlasToolsConfigDb.py            |  2 +
 .../G4AtlasTools/python/G4FieldConfig.py      | 23 +++++++-
 .../src/DetectorFieldManagerTool.cxx          | 12 +++-
 .../G4AtlasTools/src/DetectorGeometryBase.cxx |  4 +-
 .../src/FastSimulationMasterTool.h            |  2 +-
 .../src/GlobalFieldManagerTool.cxx            | 28 ++++++++-
 .../src/SensitiveDetectorMasterTool.h         |  2 +-
 .../src/TightMuonElseNoFieldManager.cxx       | 38 ++++++++++++
 .../src/TightMuonElseNoFieldManager.h         | 44 ++++++++++++++
 .../src/TightMuonSteppingFieldManager.cxx     | 59 +++++++++++++++++++
 .../src/TightMuonSteppingFieldManager.h       | 48 +++++++++++++++
 18 files changed, 274 insertions(+), 13 deletions(-)
 create mode 100644 Simulation/G4Atlas/G4AtlasTools/src/TightMuonElseNoFieldManager.cxx
 create mode 100644 Simulation/G4Atlas/G4AtlasTools/src/TightMuonElseNoFieldManager.h
 create mode 100644 Simulation/G4Atlas/G4AtlasTools/src/TightMuonSteppingFieldManager.cxx
 create mode 100644 Simulation/G4Atlas/G4AtlasTools/src/TightMuonSteppingFieldManager.h

diff --git a/Simulation/G4Atlas/G4AtlasTools/G4AtlasTools/DetectorFieldManagerTool.h b/Simulation/G4Atlas/G4AtlasTools/G4AtlasTools/DetectorFieldManagerTool.h
index b3cc044d959..8fe96097edd 100644
--- a/Simulation/G4Atlas/G4AtlasTools/G4AtlasTools/DetectorFieldManagerTool.h
+++ b/Simulation/G4Atlas/G4AtlasTools/G4AtlasTools/DetectorFieldManagerTool.h
@@ -39,6 +39,9 @@ class DetectorFieldManagerTool : public G4FieldManagerToolBase
     /// List of volumes to assign this field configuration to
     std::vector<std::string> m_volumeList;
 
+    /// Option for muons feeling the B-field only
+    bool m_muonOnlyField;
+
     /// My field manager
     thread_utils::ThreadLocalOwner<G4FieldManager> m_fieldMgrHolder;
 
diff --git a/Simulation/G4Atlas/G4AtlasTools/G4AtlasTools/EnvelopeTool.h b/Simulation/G4Atlas/G4AtlasTools/G4AtlasTools/EnvelopeTool.h
index 3a7d39bebbe..6af348c0c96 100644
--- a/Simulation/G4Atlas/G4AtlasTools/G4AtlasTools/EnvelopeTool.h
+++ b/Simulation/G4Atlas/G4AtlasTools/G4AtlasTools/EnvelopeTool.h
@@ -27,7 +27,7 @@ public:
   
   /** virtual methods being implemented here */
   
-  virtual void BuildGeometry();
+  virtual void BuildGeometry() override;
   
 private:
   ServiceHandle<IEnvelopeDefSvc> m_envelopeDefSvc;
diff --git a/Simulation/G4Atlas/G4AtlasTools/G4AtlasTools/FastSimulationBase.h b/Simulation/G4Atlas/G4AtlasTools/G4AtlasTools/FastSimulationBase.h
index 8f995eae457..9e038bcc22a 100644
--- a/Simulation/G4Atlas/G4AtlasTools/G4AtlasTools/FastSimulationBase.h
+++ b/Simulation/G4Atlas/G4AtlasTools/G4AtlasTools/FastSimulationBase.h
@@ -36,7 +36,7 @@ class FastSimulationBase : virtual public IFastSimulation, public AthAlgTool {
   virtual StatusCode EndOfAthenaEvent() override { return StatusCode::SUCCESS; }
 
   /** Query interface method to make athena happy */
-  virtual StatusCode queryInterface(const InterfaceID&, void**);
+  virtual StatusCode queryInterface(const InterfaceID&, void**) override;
 
  protected:
   /// Retrieve the current Fast Simulation Model. In hive, this means the
diff --git a/Simulation/G4Atlas/G4AtlasTools/G4AtlasTools/GlobalFieldManagerTool.h b/Simulation/G4Atlas/G4AtlasTools/G4AtlasTools/GlobalFieldManagerTool.h
index 7e79134ae07..c9b35c66a7f 100644
--- a/Simulation/G4Atlas/G4AtlasTools/G4AtlasTools/GlobalFieldManagerTool.h
+++ b/Simulation/G4Atlas/G4AtlasTools/G4AtlasTools/GlobalFieldManagerTool.h
@@ -7,6 +7,7 @@
 
 // Local includes
 #include "G4AtlasTools/G4FieldManagerToolBase.h"
+#include "G4AtlasTools/ThreadLocalHolder.h"
 
 
 /** @class GlobalFieldManagerTool GlobalFieldManagerTool.h "G4AtlasTools/GlobalFieldManagerTool.h"
@@ -33,6 +34,12 @@ class GlobalFieldManagerTool : public G4FieldManagerToolBase
 
   protected:
 
+    /// Tight muon stepping parameters via the field manager's configure for track
+    bool m_useTightMuonStepping;
+
+    /// My field manager -- populated only in the case that we use tight muon stepping
+    thread_utils::ThreadLocalOwner<G4FieldManager> m_fieldMgrHolder;
+
 };
 
 #endif // G4ATLASTOOLS_GlobalFieldManagerTool_H
diff --git a/Simulation/G4Atlas/G4AtlasTools/G4AtlasTools/SensitiveDetectorBase.h b/Simulation/G4Atlas/G4AtlasTools/G4AtlasTools/SensitiveDetectorBase.h
index 8078ad466b8..6d5502f9c87 100644
--- a/Simulation/G4Atlas/G4AtlasTools/G4AtlasTools/SensitiveDetectorBase.h
+++ b/Simulation/G4Atlas/G4AtlasTools/G4AtlasTools/SensitiveDetectorBase.h
@@ -66,7 +66,7 @@ class SensitiveDetectorBase : virtual public ISensitiveDetector, public AthAlgTo
   virtual StatusCode Gather() override { return StatusCode::SUCCESS; }
 
   /** Query interface method to make athena happy */
-  virtual StatusCode queryInterface(const InterfaceID&, void**);
+  virtual StatusCode queryInterface(const InterfaceID&, void**) override;
 
  protected:
 
diff --git a/Simulation/G4Atlas/G4AtlasTools/G4AtlasTools/UserActionBase.h b/Simulation/G4Atlas/G4AtlasTools/G4AtlasTools/UserActionBase.h
index 3a2ba5d35b3..20effbe2735 100644
--- a/Simulation/G4Atlas/G4AtlasTools/G4AtlasTools/UserActionBase.h
+++ b/Simulation/G4Atlas/G4AtlasTools/G4AtlasTools/UserActionBase.h
@@ -47,9 +47,9 @@ class UserActionBase : virtual public IUserAction , public AthAlgTool {
 
   virtual std::vector<std::string > GetRegions() override final {return m_regions;};
 
-  virtual StatusCode queryInterface(const InterfaceID&, void**);
+  virtual StatusCode queryInterface(const InterfaceID&, void**) override;
 
-  virtual void setManagers(G4EventManager* em, G4TrackingManager* tm, G4StackManager* stam, G4SteppingManager* stem){
+  virtual void setManagers(G4EventManager* em, G4TrackingManager* tm, G4StackManager* stam, G4SteppingManager* stem) override final {
     m_fpEventManager=em;
     m_stackManager=stam;
     m_fpSteppingManager=stem;
diff --git a/Simulation/G4Atlas/G4AtlasTools/python/G4AtlasToolsConfig.py b/Simulation/G4Atlas/G4AtlasTools/python/G4AtlasToolsConfig.py
index 48873fecc93..90053594f8d 100644
--- a/Simulation/G4Atlas/G4AtlasTools/python/G4AtlasToolsConfig.py
+++ b/Simulation/G4Atlas/G4AtlasTools/python/G4AtlasToolsConfig.py
@@ -98,7 +98,8 @@ def generateCaloSensitiveDetectorList():
                                    'LArHECSensitiveDetector','LArMiniFCALSensitiveDetector']
         if hasattr(DetFlags.simulate, 'HGTD_on') and DetFlags.simulate.HGTD_on():
             SensitiveDetectorList += [ 'HGTDSensorSD' ]
-        SensitiveDetectorList += [ 'MinBiasScintillatorSD' ]
+        else:
+            SensitiveDetectorList += [ 'MinBiasScintillatorSD' ]
         from G4AtlasApps.SimFlags import simFlags
         if simFlags.CalibrationRun.get_Value() in ['LAr', 'LAr+Tile']:
             SensitiveDetectorList += [ 'LArDeadSensitiveDetector','LArInactiveSensitiveDetector','LArActiveSensitiveDetector' ]
@@ -204,6 +205,8 @@ def getEmptySensitiveDetectorMasterTool(name="EmptySensitiveDetectorMasterTool",
 
 def getPhysicsListToolBase(name="PhysicsListToolBase", **kwargs):
     PhysOptionList = ["G4StepLimitationTool"]
+    from G4AtlasApps.SimFlags import simFlags
+    PhysOptionList += simFlags.PhysicsOptions.get_Value()
     PhysDecaysList = []
     from AthenaCommon.DetFlags import DetFlags
     if DetFlags.simulate.TRT_on():
diff --git a/Simulation/G4Atlas/G4AtlasTools/python/G4AtlasToolsConfigDb.py b/Simulation/G4Atlas/G4AtlasTools/python/G4AtlasToolsConfigDb.py
index 5f15cb0097b..211a22477f3 100644
--- a/Simulation/G4Atlas/G4AtlasTools/python/G4AtlasToolsConfigDb.py
+++ b/Simulation/G4Atlas/G4AtlasTools/python/G4AtlasToolsConfigDb.py
@@ -63,9 +63,11 @@ addTool("G4AtlasTools.G4PhysicsRegionConfig.getCavernShaftsConcretePhysicsRegion
 addTool("G4AtlasTools.G4PhysicsRegionConfig.getSCTSiliconPhysicsRegionTool", 'SCTSiliconPhysicsRegionTool')
 
 addTool("G4AtlasTools.G4FieldConfig.getATLASFieldManagerTool", 'ATLASFieldManager')
+addTool("G4AtlasTools.G4FieldConfig.getTightMuonsATLASFieldManagerTool", 'TightMuonsATLASFieldManager')
 addTool("G4AtlasTools.G4FieldConfig.getClassicFieldManagerTool", 'ClassicFieldManager')
 addTool("G4AtlasTools.G4FieldConfig.getBeamPipeFieldManagerTool", 'BeamPipeFieldManager')
 addTool("G4AtlasTools.G4FieldConfig.getInDetFieldManagerTool", 'InDetFieldManager')
+addTool("G4AtlasTools.G4FieldConfig.getMuonsOnlyInCaloFieldManagerTool", 'MuonsOnlyInCaloFieldManager')
 addTool("G4AtlasTools.G4FieldConfig.getMuonFieldManagerTool", 'MuonFieldManager')
 addTool("G4AtlasTools.G4FieldConfig.getQ1FwdFieldMangerTool", 'Q1FwdFieldManager')
 addTool("G4AtlasTools.G4FieldConfig.getQ2FwdFieldMangerTool", 'Q2FwdFieldManager')
diff --git a/Simulation/G4Atlas/G4AtlasTools/python/G4FieldConfig.py b/Simulation/G4Atlas/G4AtlasTools/python/G4FieldConfig.py
index 0a3f48cf284..f532d1f40e1 100644
--- a/Simulation/G4Atlas/G4AtlasTools/python/G4FieldConfig.py
+++ b/Simulation/G4Atlas/G4AtlasTools/python/G4FieldConfig.py
@@ -7,6 +7,16 @@ def getATLASFieldManagerTool(name='ATLASFieldManager', **kwargs):
     from G4AtlasApps.SimFlags import simFlags
     kwargs.setdefault("IntegratorStepper", simFlags.G4Stepper.get_Value())
     kwargs.setdefault("FieldSvc", "StandardField")
+    kwargs.setdefault("UseTightMuonStepping", False)
+    if simFlags.EquationOfMotion.statusOn:
+        kwargs.setdefault("EquationOfMotion", simFlags.EquationOfMotion.get_Value() )
+    return CfgMgr.GlobalFieldManagerTool(name, **kwargs)
+
+def getTightMuonsATLASFieldManagerTool(name='TightMuonsATLASFieldManager', **kwargs):
+    from G4AtlasApps.SimFlags import simFlags
+    kwargs.setdefault("IntegratorStepper", simFlags.G4Stepper.get_Value())
+    kwargs.setdefault("FieldSvc", "StandardField")
+    kwargs.setdefault("UseTightMuonStepping",True)
     if simFlags.EquationOfMotion.statusOn:
         kwargs.setdefault("EquationOfMotion", simFlags.EquationOfMotion.get_Value() )
     return CfgMgr.GlobalFieldManagerTool(name, **kwargs)
@@ -18,7 +28,8 @@ def getClassicFieldManagerTool(name='ClassicFieldManager', **kwargs):
 def getBasicDetectorFieldManagerTool(name='BasicDetectorFieldManager', **kwargs):
     from G4AtlasApps.SimFlags import simFlags
     kwargs.setdefault("IntegratorStepper", simFlags.G4Stepper.get_Value())
-    kwargs.setdefault("FieldSvc",           "StandardField")
+    kwargs.setdefault("FieldSvc",          "StandardField")
+    kwargs.setdefault('MuonOnlyField',     False)
     if simFlags.EquationOfMotion.statusOn:
         kwargs.setdefault("EquationOfMotion", simFlags.EquationOfMotion.get_Value() )
     return CfgMgr.DetectorFieldManagerTool(name, **kwargs)
@@ -41,6 +52,16 @@ def getInDetFieldManagerTool(name='InDetFieldManager', **kwargs):
     kwargs.setdefault('MinimumEpsilonStep', 0.00001)
     return getBasicDetectorFieldManagerTool(name, **kwargs)
 
+def getMuonsOnlyInCaloFieldManagerTool(name='MuonsOnlyInCaloFieldManager', **kwargs):
+    kwargs.setdefault("LogicalVolumes", ['CALO::CALO'])
+    #kwargs.setdefault('DeltaChord',         0.00000002)
+    kwargs.setdefault('DeltaIntersection',  0.00000002)
+    kwargs.setdefault('DeltaOneStep',       0.000001)
+    kwargs.setdefault('MaximumEpsilonStep', 0.0000009)
+    kwargs.setdefault('MinimumEpsilonStep', 0.000001)
+    kwargs.setdefault('MuonOnlyField',      True)
+    return getBasicDetectorFieldManagerTool(name, **kwargs)
+
 def getMuonFieldManagerTool(name='MuonFieldManager', **kwargs):
     kwargs.setdefault("LogicalVolumes", ['MUONQ02::MUONQ02'])
     #kwargs.setdefault('DeltaChord',         0.00000002)
diff --git a/Simulation/G4Atlas/G4AtlasTools/src/DetectorFieldManagerTool.cxx b/Simulation/G4Atlas/G4AtlasTools/src/DetectorFieldManagerTool.cxx
index b63a3b4abfa..5ef53756134 100644
--- a/Simulation/G4Atlas/G4AtlasTools/src/DetectorFieldManagerTool.cxx
+++ b/Simulation/G4Atlas/G4AtlasTools/src/DetectorFieldManagerTool.cxx
@@ -5,6 +5,9 @@
 // Main header
 #include "G4AtlasTools/DetectorFieldManagerTool.h"
 
+// From this package
+#include "TightMuonElseNoFieldManager.h"
+
 // Geant4 includes
 #include "G4MagneticField.hh"
 #include "G4FieldManager.hh"
@@ -22,6 +25,8 @@ DetectorFieldManagerTool::DetectorFieldManagerTool(const std::string& type,
 {
   declareProperty("LogicalVolumes", m_volumeList,
                   "List of volumes to which the field will be applied");
+  declareProperty("MuonOnlyField", m_muonOnlyField,
+                  "Only muons experience the magnetic field");
 }
 
 //-----------------------------------------------------------------------------
@@ -42,7 +47,12 @@ StatusCode DetectorFieldManagerTool::initializeField()
     }
 
     // Create a new field manager
-    auto fieldMgr = new G4FieldManager();
+    G4FieldManager * fieldMgr = nullptr;
+    if (m_muonOnlyField){
+      fieldMgr = new TightMuonElseNoFieldManager();
+    } else {
+      fieldMgr = new G4FieldManager();
+    }
 
     // Save it in the TL holder
     m_fieldMgrHolder.set(fieldMgr);
diff --git a/Simulation/G4Atlas/G4AtlasTools/src/DetectorGeometryBase.cxx b/Simulation/G4Atlas/G4AtlasTools/src/DetectorGeometryBase.cxx
index dde15794cd0..bdfa8fad096 100644
--- a/Simulation/G4Atlas/G4AtlasTools/src/DetectorGeometryBase.cxx
+++ b/Simulation/G4Atlas/G4AtlasTools/src/DetectorGeometryBase.cxx
@@ -97,8 +97,8 @@ void DetectorGeometryBase::SetRotationAndOffset()
       //FIXME probably a neater way to do this part.
       m_envelope.theRotation=new G4RotationMatrix;
       m_envelope.theRotation->rotateX(m_rotateX);
-      m_envelope.theRotation->rotateX(m_rotateY);
-      m_envelope.theRotation->rotateX(m_rotateZ);
+      m_envelope.theRotation->rotateY(m_rotateY);
+      m_envelope.theRotation->rotateZ(m_rotateZ);
       if (m_envelope.thePositionedVolume)
         m_envelope.thePositionedVolume->SetRotation(m_envelope.theRotation);
     }
diff --git a/Simulation/G4Atlas/G4AtlasTools/src/FastSimulationMasterTool.h b/Simulation/G4Atlas/G4AtlasTools/src/FastSimulationMasterTool.h
index 6afe83fc048..f8e72aa726c 100644
--- a/Simulation/G4Atlas/G4AtlasTools/src/FastSimulationMasterTool.h
+++ b/Simulation/G4Atlas/G4AtlasTools/src/FastSimulationMasterTool.h
@@ -20,7 +20,7 @@ class FastSimulationMasterTool : public AthAlgTool , public virtual IFastSimulat
   virtual ~FastSimulationMasterTool() {}
 
   // Gaudi methods
-  virtual StatusCode queryInterface( const InterfaceID& riid, void** ppvInterface );
+  virtual StatusCode queryInterface( const InterfaceID& riid, void** ppvInterface ) override;
   static const InterfaceID& interfaceID() { return IFastSimulationMasterTool::interfaceID(); }
 
   // Base class methods
diff --git a/Simulation/G4Atlas/G4AtlasTools/src/GlobalFieldManagerTool.cxx b/Simulation/G4Atlas/G4AtlasTools/src/GlobalFieldManagerTool.cxx
index 30cc295d150..b8ba6f02cae 100644
--- a/Simulation/G4Atlas/G4AtlasTools/src/GlobalFieldManagerTool.cxx
+++ b/Simulation/G4Atlas/G4AtlasTools/src/GlobalFieldManagerTool.cxx
@@ -5,6 +5,9 @@
 // Main header
 #include "G4AtlasTools/GlobalFieldManagerTool.h"
 
+// Local package include
+#include "TightMuonSteppingFieldManager.h"
+
 // Geant4 includes
 #include "G4TransportationManager.hh"
 #include "G4VUserPrimaryGeneratorAction.hh"
@@ -23,6 +26,8 @@ GlobalFieldManagerTool::GlobalFieldManagerTool(const std::string& type,
                                                const IInterface* parent)
   : G4FieldManagerToolBase(type, name, parent)
 {
+  declareProperty("UseTightMuonStepping", m_useTightMuonStepping=false,
+                  "Use tight muon stepping parameters by default");
 }
 
 //-----------------------------------------------------------------------------
@@ -39,7 +44,28 @@ StatusCode GlobalFieldManagerTool::initializeField()
 
     // Retrieve the global field manager
     auto transpManager = G4TransportationManager::GetTransportationManager();
-    auto fieldMgr = transpManager->GetFieldManager();
+    G4FieldManager* fieldMgr(nullptr);
+    if (m_useTightMuonStepping){
+      // In the case of tight stepping we need to make our own global field manager
+      // If field manager already exists for current thread, error.
+      // There is no foreseen use-case for this situation.
+      if(m_fieldMgrHolder.get()) {
+        ATH_MSG_ERROR("GlobalFieldManagerTool::initializeField() - " <<
+                      "Field manager already exists!");
+        return StatusCode::FAILURE;
+      }
+      // Create a new field manager
+      fieldMgr = new TightMuonSteppingFieldManager();
+
+      // Save it in the TL holder
+      m_fieldMgrHolder.set(fieldMgr);
+
+      // Assign it to the global field manager
+      transpManager->SetFieldManager(fieldMgr);
+    } else {
+      // Otherwise get the default from the transportation manager
+      fieldMgr = transpManager->GetFieldManager();
+    }
 
     // Configure the field manager
     fieldMgr->SetDetectorField(field);
diff --git a/Simulation/G4Atlas/G4AtlasTools/src/SensitiveDetectorMasterTool.h b/Simulation/G4Atlas/G4AtlasTools/src/SensitiveDetectorMasterTool.h
index d772e4d8b86..4b782b7ebcd 100644
--- a/Simulation/G4Atlas/G4AtlasTools/src/SensitiveDetectorMasterTool.h
+++ b/Simulation/G4Atlas/G4AtlasTools/src/SensitiveDetectorMasterTool.h
@@ -33,7 +33,7 @@ class SensitiveDetectorMasterTool : public AthAlgTool,
   virtual ~SensitiveDetectorMasterTool() {}
 
   /// Gaudi boiler plate methods
-  virtual StatusCode queryInterface( const InterfaceID& riid, void** ppvInterface );
+  virtual StatusCode queryInterface( const InterfaceID& riid, void** ppvInterface ) override;
   static const InterfaceID& interfaceID() {
     return ISensitiveDetectorMasterTool::interfaceID();
   }
diff --git a/Simulation/G4Atlas/G4AtlasTools/src/TightMuonElseNoFieldManager.cxx b/Simulation/G4Atlas/G4AtlasTools/src/TightMuonElseNoFieldManager.cxx
new file mode 100644
index 00000000000..2838d13fe21
--- /dev/null
+++ b/Simulation/G4Atlas/G4AtlasTools/src/TightMuonElseNoFieldManager.cxx
@@ -0,0 +1,38 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TightMuonElseNoFieldManager.h"
+#include "G4Track.hh"
+#include "G4MuonPlus.hh"
+#include "G4MuonMinus.hh"
+
+/// Normal constructor
+TightMuonElseNoFieldManager::TightMuonElseNoFieldManager(G4Field *detectorField, G4ChordFinder *pChordFinder, G4bool b)
+ : G4FieldManager(detectorField,pChordFinder,b)
+ , m_globalField(nullptr)
+{}
+
+/// Simple constructor
+TightMuonElseNoFieldManager::TightMuonElseNoFieldManager(G4MagneticField *detectorMagneticField)
+ : G4FieldManager(detectorMagneticField) 
+ , m_globalField(nullptr)
+{}
+
+/// The one interesting method
+void TightMuonElseNoFieldManager::ConfigureForTrack(const G4Track * track)
+{
+  // If they have not been set yet, get the settings for the global field manager
+  if (nullptr==m_globalField){
+    m_globalField = const_cast<G4Field*>(GetDetectorField());
+  }
+
+  // If this is a muon, move it in the magnetic field; otherwise turn off the stepping
+  if (track->GetDefinition()==G4MuonPlus::Definition() ||
+      track->GetDefinition()==G4MuonMinus::Definition() ){
+    SetDetectorField(m_globalField);
+  } else {
+    SetDetectorField(nullptr);
+  }
+
+}
diff --git a/Simulation/G4Atlas/G4AtlasTools/src/TightMuonElseNoFieldManager.h b/Simulation/G4Atlas/G4AtlasTools/src/TightMuonElseNoFieldManager.h
new file mode 100644
index 00000000000..c3e1ba42531
--- /dev/null
+++ b/Simulation/G4Atlas/G4AtlasTools/src/TightMuonElseNoFieldManager.h
@@ -0,0 +1,44 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TightMuonElseNoFieldManager_H
+#define TightMuonElseNoFieldManager_H
+
+/** @class TightMuonElseNoFieldManager TightMuonElseNoFieldManager.h
+ *
+ *  @brief G4FieldManager that sets tight stepping for muons; disables
+ *   magnetic field for other particles
+ *
+ *  @author Zach Marshall
+ *  @date   2016-06-01
+ */
+
+#include "G4FieldManager.hh"
+class G4Track;
+class G4Field;
+class G4ChordFinder;
+class G4MagneticField;
+
+class TightMuonElseNoFieldManager : public G4FieldManager
+{
+ public:
+  /// Constructor
+  TightMuonElseNoFieldManager(G4Field *detectorField=0, G4ChordFinder *pChordFinder=0, G4bool b=true);
+
+  /// Simple constructor
+  TightMuonElseNoFieldManager(G4MagneticField *detectorMagneticField);
+
+  /// Simple destructor
+  virtual ~TightMuonElseNoFieldManager() {}
+
+  /// The one interesting method
+  virtual void ConfigureForTrack(const G4Track *) override final;
+
+ private:
+  /** Parameters of the stepper.  This is to cache the global ones; the muon ones will be hard-coded */
+  G4Field * m_globalField;
+
+};
+
+#endif
\ No newline at end of file
diff --git a/Simulation/G4Atlas/G4AtlasTools/src/TightMuonSteppingFieldManager.cxx b/Simulation/G4Atlas/G4AtlasTools/src/TightMuonSteppingFieldManager.cxx
new file mode 100644
index 00000000000..9d5962cff4a
--- /dev/null
+++ b/Simulation/G4Atlas/G4AtlasTools/src/TightMuonSteppingFieldManager.cxx
@@ -0,0 +1,59 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TightMuonSteppingFieldManager.h"
+#include "G4Track.hh"
+#include "G4ChordFinder.hh"
+#include "G4MuonPlus.hh"
+#include "G4MuonMinus.hh"
+
+/// Normal constructor
+TightMuonSteppingFieldManager::TightMuonSteppingFieldManager(G4Field *detectorField, G4ChordFinder *pChordFinder, G4bool b)
+ : G4FieldManager(detectorField,pChordFinder,b)
+ , m_globalDeltaChord(-1.)
+ , m_globalDeltaOneStep(-1.)
+ , m_globalDeltaIntersection(-1.)
+ , m_globalMinEps(-1.)
+ , m_globalMaxEps(-1.)
+{}
+
+/// Simple constructor
+TightMuonSteppingFieldManager::TightMuonSteppingFieldManager(G4MagneticField *detectorMagneticField)
+ : G4FieldManager(detectorMagneticField) 
+ , m_globalDeltaChord(-1.)
+ , m_globalDeltaOneStep(-1.)
+ , m_globalDeltaIntersection(-1.)
+ , m_globalMinEps(-1.)
+ , m_globalMaxEps(-1.)
+{}
+
+/// The one interesting method
+void TightMuonSteppingFieldManager::ConfigureForTrack(const G4Track * track)
+{
+  // If they have not been set yet, get the settings for the global field manager
+  if (m_globalDeltaChord<0){
+    m_globalDeltaChord = GetChordFinder()->GetDeltaChord();
+    m_globalDeltaOneStep = GetDeltaOneStep();
+    m_globalDeltaIntersection = GetDeltaIntersection();
+    m_globalMinEps = GetMinimumEpsilonStep();
+    m_globalMaxEps = GetMaximumEpsilonStep();
+  }
+
+  // If this is a muon, set tight parameters; otherwise go back to the defaults
+  if (track->GetDefinition()==G4MuonPlus::Definition() ||
+      track->GetDefinition()==G4MuonMinus::Definition() ){
+    GetChordFinder()->SetDeltaChord(0.00000002);
+    SetDeltaOneStep(0.000001);
+    SetDeltaIntersection(0.00000002);
+    SetMinimumEpsilonStep(0.0000009);
+    SetMaximumEpsilonStep(0.000001);
+  } else {
+    GetChordFinder()->SetDeltaChord(m_globalDeltaChord);
+    SetDeltaOneStep(m_globalDeltaOneStep);
+    SetDeltaIntersection(m_globalDeltaIntersection);
+    SetMinimumEpsilonStep(m_globalMinEps);
+    SetMaximumEpsilonStep(m_globalMaxEps);
+  }
+
+}
diff --git a/Simulation/G4Atlas/G4AtlasTools/src/TightMuonSteppingFieldManager.h b/Simulation/G4Atlas/G4AtlasTools/src/TightMuonSteppingFieldManager.h
new file mode 100644
index 00000000000..577815ab548
--- /dev/null
+++ b/Simulation/G4Atlas/G4AtlasTools/src/TightMuonSteppingFieldManager.h
@@ -0,0 +1,48 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TightMuonSteppingFieldManager_H
+#define TightMuonSteppingFieldManager_H
+
+/** @class TightMuonSteppingFieldManager TightMuonSteppingFieldManager.h
+ *
+ *  @brief G4FieldManager that sets tight stepping for muons; caches global
+ *   values for other particles
+ *
+ *  @author Zach Marshall
+ *  @date   2016-06-01
+ */
+
+#include "G4FieldManager.hh"
+class G4Track;
+class G4Field;
+class G4ChordFinder;
+class G4MagneticField;
+
+class TightMuonSteppingFieldManager : public G4FieldManager
+{
+ public:
+  /// Constructor
+  TightMuonSteppingFieldManager(G4Field *detectorField=0, G4ChordFinder *pChordFinder=0, G4bool b=true);
+
+  /// Simple constructor
+  TightMuonSteppingFieldManager(G4MagneticField *detectorMagneticField);
+
+  /// Simple destructor
+  virtual ~TightMuonSteppingFieldManager() {}
+
+  /// The one interesting method
+  virtual void ConfigureForTrack(const G4Track *) override final;
+
+ private:
+  /** Parameters of the stepper.  This is to cache the global ones; the muon ones will be hard-coded */
+  double m_globalDeltaChord;
+  double m_globalDeltaOneStep;
+  double m_globalDeltaIntersection;
+  double m_globalMinEps;
+  double m_globalMaxEps;
+
+};
+
+#endif
\ No newline at end of file
-- 
GitLab