diff --git a/Tracking/TrkExtrapolation/TrkExTools/TrkExTools/Extrapolator.h b/Tracking/TrkExtrapolation/TrkExTools/TrkExTools/Extrapolator.h
index 5c7b7c2fb4c9cd6452bc99545d1e84a3e6f62b24..1eb5480281f0f6dddc0fa9132e8d876c1c148261 100755
--- a/Tracking/TrkExtrapolation/TrkExTools/TrkExTools/Extrapolator.h
+++ b/Tracking/TrkExtrapolation/TrkExTools/TrkExTools/Extrapolator.h
@@ -12,46 +12,46 @@
 // Gaudi/StoreGate
 #include "AthenaBaseComps/AthAlgTool.h"
 #include "AthenaBaseComps/AthCheckedComponent.h"
+#include "TrkExInterfaces/IExtrapolator.h"
+
 #include "GaudiKernel/ToolHandle.h"
 
-// Event Context
-#include "GaudiKernel/EventContext.h"
+
 
 // Trk
-#include "TrkDetDescrUtils/GeometrySignature.h"
-#include "TrkEventPrimitives/ParticleHypothesis.h"
-#include "TrkEventPrimitives/PropDirection.h"
-#include "TrkExInterfaces/IExtrapolator.h"
-#include "TrkExInterfaces/IMaterialEffectsUpdator.h"
-#include "TrkExInterfaces/INavigator.h"
-#include "TrkExInterfaces/IPropagator.h"
-#include "TrkExUtils/ExtrapolationCache.h"
-#include "TrkGeometry/MagneticFieldProperties.h"
-#include "TrkGeometry/TrackingVolume.h"
-#include "TrkGeometry/TrackingGeometry.h"
-#include "TrkNeutralParameters/NeutralParameters.h"
-#include "TrkParameters/TrackParameters.h"
-#include "TrkSurfaces/BoundaryCheck.h"
-#include "TrkSurfaces/PlaneSurface.h"
-#include "TrkVolumes/BoundarySurface.h"
-#include "TrkVolumes/BoundarySurfaceFace.h"
-// STL
-#include <cstring>
-#include <utility>
+#include "TrkEventPrimitives/ParticleHypothesis.h" //enum
+#include "TrkEventPrimitives/PropDirection.h" //enum
+
+#include "TrkExInterfaces/IMaterialEffectsUpdator.h"// in tool handle array
+#include "TrkExInterfaces/INavigator.h" //in tool handle
+#include "TrkExInterfaces/IPropagator.h" //in tool handle
+#include "TrkGeometry/MagneticFieldProperties.h" //member
+
+#include "TrkNeutralParameters/NeutralParameters.h" //typedef
+#include "TrkParameters/TrackParameters.h" //template parameter in typedef
+#include "TrkSurfaces/BoundaryCheck.h" //template parameter in typedef
+
+#include "LocalExtrapolatorCache.h" //for Trk::Cache
 
-#include <map>
-#include <vector>
 // Amg
-#include "EventPrimitives/EventPrimitives.h"
-#include "GeoPrimitives/GeoPrimitives.h"
+#include "EventPrimitives/EventPrimitives.h" //Amg::Vector etc
 // xAOD
-#include "xAODTracking/NeutralParticle.h"
-#include "xAODTracking/TrackParticle.h"
+#include "xAODTracking/NeutralParticle.h" //typedef
+#include "xAODTracking/TrackParticle.h" //typedef
 
 #include "ObjContainer.h"
 #include <Gaudi/Accumulators.h>
+// STL
+#include <cstring>
+#include <utility>
+#include <memory>
+#include <map>
+#include <vector>
 
 class MsgStream;
+class EventContext;
+
+
 namespace Trk {
 class Track;
 class Surface;
@@ -60,14 +60,12 @@ class Volume;
 class DetachedTrackingVolume;
 class TrackingGeometry;
 class TrackParticleBase;
-class IPropagator;
 class IDynamicLayerCreator;
-class INavigator;
 class IMultipleScatteringUpdator;
 class IEnergyLossUpdator;
-class IPropagator;
 class AlignableTrackingVolume;
 class ExtrapolationCache;
+class TrackingVolume;
 
 typedef std::vector<Trk::TrackParameters*> TrackParametersPtrVector;
 typedef std::vector<std::unique_ptr<Trk::TrackParameters>> TrackParametersUVector;
@@ -77,48 +75,6 @@ using TrackParmContainer = ObjContainer<Trk::TrackParameters>;
 using TrackParmPtr = ObjRef;
 using ManagedTrackParmPtr = ObjPtr<Trk::TrackParameters>;
 
-/** @struct ParametersAtBoundarySurface
-  has only three member
-  - BoundarySurface
-  - TrackParameters
-  - bool that indicated the deletion of the TrackParameters
-  */
-struct ParametersNextVolume
-{
-  //!< the members
-  const TrackingVolume* nextVolume;
-  ManagedTrackParmPtr nextParameters;
-  ManagedTrackParmPtr navParameters;
-  BoundarySurfaceFace exitFace;
-
-  ParametersNextVolume(TrackParmContainer& track_parm_container)
-    : nextVolume(nullptr)
-    , nextParameters(track_parm_container)
-    , navParameters(track_parm_container)
-    , exitFace(undefinedFace)
-  {
-  }
-
-  //!< update the boundaryInformation
-  void boundaryInformation(const TrackingVolume* tvol,
-                           ManagedTrackParmPtr nextPars,
-                           ManagedTrackParmPtr navPars,
-                           BoundarySurfaceFace face = undefinedFace)
-  {
-    nextVolume = tvol;
-    nextParameters = std::move(nextPars);
-    navParameters = std::move(navPars);
-    exitFace = face;
-  }
-  //!< reset the boundary information by invalidating it
-  void resetBoundaryInformation()
-  {
-    nextVolume = nullptr;
-    exitFace = undefinedFace;
-    nextParameters = ManagedTrackParmPtr();
-    navParameters = ManagedTrackParmPtr();
-  }
-};
 
 /**
   @class Extrapolator
@@ -329,138 +285,7 @@ private:
    * Cache to be passed to and between the private methods
    */
   typedef std::vector<std::pair<std::unique_ptr<Trk::TrackParameters>, int>> identifiedParameters_t;
-  struct Cache
-  {
-
-    TrackParmContainer m_trackParmContainer;
-    //!< parameters to be used for final propagation in case of fallback
-    ManagedTrackParmPtr m_lastValidParameters;
-    //!< return helper for parameters and boundary
-    ParametersNextVolume m_parametersAtBoundary;
-    //!< Caches per MaterialUpdator
-    std::vector<Trk::IMaterialEffectsUpdator::ICache> m_MaterialUpCache;
-    //!<  internal switch for resolved configuration
-    bool m_dense = false;
-    //!< Flag the recall solution
-    bool m_recall = false;
-    bool m_robustSampling = true;
-    bool m_ownParametersOnDetElements = true;
-    unsigned int m_layerResolved{};
-    unsigned int m_methodSequence = 0;
-    const Surface* m_destinationSurface = nullptr;
-    //!< the boundary volume check
-    const Volume* m_boundaryVolume = nullptr;
-    //!< Destination Surface for recall
-    const Surface* m_recallSurface = nullptr;
-    //!< Destination Layer for recall
-    const Layer* m_recallLayer = nullptr;
-    //!< Destination TrackingVolume for recall
-    const TrackingVolume* m_recallTrackingVolume = nullptr;
-    const Trk::TrackingVolume* m_currentStatic = nullptr;
-    const Trk::TrackingVolume* m_currentDense = nullptr;
-    const Trk::TrackingVolume* m_highestVolume = nullptr;
-    //!< return helper for parameters on detector elements
-    TrackParametersPtrVector* m_parametersOnDetElements = nullptr;
-    //!< cache layer with last material update
-    const Layer* m_lastMaterialLayer = nullptr;
-    //!< cache for collecting the total X0 ans Eloss
-    Trk::ExtrapolationCache* m_extrapolationCache = nullptr;
-    //!< cache pointer for Eloss
-    const Trk::EnergyLoss* m_cacheEloss = nullptr;
-    //!< cache of TrackStateOnSurfaces
-    std::vector<const Trk::TrackStateOnSurface*>* m_matstates = nullptr;
-    //!< cache of Transport Jacobians
-    std::vector<Trk::TransportJacobian*>* m_jacs = nullptr;
-    // for active volumes
-    std::unique_ptr<identifiedParameters_t> m_identifiedParameters;
-
-    const Trk::TrackingGeometry *m_trackingGeometry = nullptr;
-    double m_path{};
-
-    std::pair<unsigned int, unsigned int> m_denseResolved;
-
-    std::vector<DestSurf> m_staticBoundaries;
-    std::vector<DestSurf> m_detachedBoundaries;
-    std::vector<DestSurf> m_denseBoundaries;
-    std::vector<DestSurf> m_navigBoundaries;
-    std::vector<DestSurf> m_layers;
-
-    std::vector<std::pair<const Trk::DetachedTrackingVolume*, unsigned int>> m_detachedVols;
-    std::vector<std::pair<const Trk::TrackingVolume*, unsigned int>> m_denseVols;
-    std::vector<std::pair<const Trk::TrackingVolume*, const Trk::Layer*>> m_navigLays;
-    std::vector<std::pair<const Trk::Surface*, Trk::BoundaryCheck>> m_navigSurfs;
-    std::vector<const Trk::DetachedTrackingVolume*> m_navigVols;
-    std::vector<std::pair<const Trk::TrackingVolume*, unsigned int>> m_navigVolsInt;
-
-    TrackParmContainer& trackParmContainer() { return m_trackParmContainer; }
-
- 
-    ManagedTrackParmPtr manage(std::unique_ptr<Trk::TrackParameters>&& parm)
-    {
-      return ManagedTrackParmPtr(trackParmContainer(), std::move(parm));
-    }
-    ManagedTrackParmPtr manage(TrackParmPtr parm)
-    {
-      return ManagedTrackParmPtr(trackParmContainer(), parm);
-    }
-    ManagedTrackParmPtr manage() { return ManagedTrackParmPtr(trackParmContainer()); }
-
-    const Trk::TrackingGeometry *trackingGeometry( const Trk::INavigator &navigator, const EventContext &ctx) {
-       if (!m_trackingGeometry) {
-          m_trackingGeometry = navigator.trackingGeometry(ctx);
-       }
-       return m_trackingGeometry;
-    }
-
-    const Trk::TrackingVolume *volume(const EventContext&, const Amg::Vector3D& gp) const {
-       assert(m_trackingGeometry);
-       return m_trackingGeometry->lowestTrackingVolume(gp);
-    }
-
-    Cache()
-      : m_trackParmContainer(128)
-      , // always reserve some space; still occasionally more slots are
-        // needed; above 150 there are very few cases the max in q431 was 257
-      m_lastValidParameters(m_trackParmContainer)
-      , m_parametersAtBoundary(m_trackParmContainer)
-    {
-      m_navigSurfs.reserve(1024);
-      m_navigVols.reserve(64);
-      m_navigVolsInt.reserve(64);
-    }
-    ~Cache()
-    {
-      s_navigSurfsMax.update(m_navigSurfs.size());
-      s_navigVolsMax.update(m_navigVols.size());
-      s_navigVolsIntMax.update(m_navigVols.size());
-      if (m_ownParametersOnDetElements && m_parametersOnDetElements) {
-        for (const Trk::TrackParameters* parm : *m_parametersOnDetElements) {
-          delete parm;
-        }
-      }
-      s_containerSizeMax.update(trackParmContainer().size());
-    }
-
-    /**
-     * struct for accumulating stat counters
-     */
-    struct AtomicMax
-    {
-      void update(size_t val)
-      {
-        while (val > m_maxVal) {
-          val = m_maxVal.exchange(val);
-        }
-      }
-      size_t val() const { return m_maxVal; }
-      std::atomic<size_t> m_maxVal = 0;
-    };
-    static AtomicMax s_navigSurfsMax ATLAS_THREAD_SAFE;
-    static AtomicMax s_navigVolsMax ATLAS_THREAD_SAFE;
-    static AtomicMax s_navigVolsIntMax ATLAS_THREAD_SAFE;
-    static AtomicMax s_containerSizeMax ATLAS_THREAD_SAFE;
-    static bool s_reported ATLAS_THREAD_SAFE;
-  };
+  
 
   /**
    * Actual heavy lifting implementation for
@@ -783,23 +608,7 @@ private:
   /** Access the subPropagator to the given volume*/
   const IMaterialEffectsUpdator* subMaterialEffectsUpdator(const TrackingVolume& tvol) const;
 
-  /** Get the IMaterialEffectsUpdator::ICache  for the MaterialEffectsUpdator*/
-  IMaterialEffectsUpdator::ICache& subMaterialEffectsUpdatorCache(Cache& cache,
-                                                                  const TrackingVolume& tvol) const;
-
-  /** Prepare the IMaterialEffectsUpdator::ICache for each
-   * Material Effects updator */
-  void populateMatEffUpdatorCache(Cache& cache) const;
-
-  /** Private method for setting recall Information */
-  void setRecallInformation(Cache& cache,
-                            const Surface&,
-                            const Layer&,
-                            const TrackingVolume&) const;
-
-  /** Private method for resetting the recallInformation */
-  void resetRecallInformation(Cache& cache) const;
-
+ 
   /** Private method to return from extrapolate() main method,
       cleans up, calls model action or validation action, empties garbage bin and leaves */
   const Trk::TrackParameters* returnResult(Cache& cache, const Trk::TrackParameters* result) const;
@@ -817,8 +626,7 @@ private:
                                  Trk::PropDirection propDir,
                                  Trk::ParticleHypothesis) const;
 
-  void dumpCache(Cache& cache, const std::string& txt) const;
-  bool checkCache(Cache& cache, const std::string& txt) const;
+  
 
   /** Private method for conversion of the synchronized geometry signature to
    * the natural subdetector ordering */
diff --git a/Tracking/TrkExtrapolation/TrkExTools/TrkExTools/Extrapolator.icc b/Tracking/TrkExtrapolation/TrkExTools/TrkExTools/Extrapolator.icc
index fd0a654b9a4dcde4b39040a40137b6cdf680b8d9..f6544401e628e9f14e673628a2f90404f207cc22 100644
--- a/Tracking/TrkExtrapolation/TrkExTools/TrkExTools/Extrapolator.icc
+++ b/Tracking/TrkExtrapolation/TrkExTools/TrkExTools/Extrapolator.icc
@@ -40,43 +40,6 @@ Extrapolator::subMaterialEffectsUpdator(const Trk::TrackingVolume& tvol) const
            : nullptr;
 }
 
-inline IMaterialEffectsUpdator::ICache&
-Extrapolator::subMaterialEffectsUpdatorCache(Cache& cache,
-                                             const TrackingVolume& tvol) const
-{
-  return cache.m_MaterialUpCache[tvol.geometrySignature()];
-}
-
-inline void
-Extrapolator::populateMatEffUpdatorCache(Cache& cache) const
-{
-  size_t numUpdaters = m_subupdaters.size();
-  cache.m_MaterialUpCache.reserve(numUpdaters);
-  for (size_t i = 0; i < numUpdaters; ++i) {
-    cache.m_MaterialUpCache.emplace_back(m_subupdaters[i]->getCache());
-  }
-}
-
-inline void
-Extrapolator::setRecallInformation(Cache& cache,
-                                   const Surface& rsf,
-                                   const Layer& rlay,
-                                   const TrackingVolume& rvol) const
-{
-  cache.m_recall = true;
-  cache.m_recallSurface = &rsf;
-  cache.m_recallLayer = &rlay;
-  cache.m_recallTrackingVolume = &rvol;
-}
-
-inline void
-Extrapolator::resetRecallInformation(Cache& cache) const
-{
-  cache.m_recall = false;
-  cache.m_recallSurface = nullptr;
-  cache.m_recallLayer = nullptr;
-  cache.m_recallTrackingVolume = nullptr;
-}
 
 inline const Trk::TrackParameters*
 Extrapolator::returnResult(Cache& cache,
diff --git a/Tracking/TrkExtrapolation/TrkExTools/TrkExTools/LocalExtrapolatorCache.h b/Tracking/TrkExtrapolation/TrkExTools/TrkExTools/LocalExtrapolatorCache.h
new file mode 100644
index 0000000000000000000000000000000000000000..faf39528ea6f32405fb2d27625e51bc6c445acd8
--- /dev/null
+++ b/Tracking/TrkExtrapolation/TrkExTools/TrkExTools/LocalExtrapolatorCache.h
@@ -0,0 +1,184 @@
+
+/*
+   Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
+ */
+ 
+#ifndef TRKEXTOOLS_LOCALEXCACHE_H
+#define TRKEXTOOLS_LOCALEXCACHE_H
+#include "ObjContainer.h"
+#include "TrkParameters/TrackParameters.h"
+#include "ParametersNextVolume.h"
+#include "TrkExInterfaces/IMaterialEffectsUpdator.h"
+#include "TrkGeometry/TrackingGeometry.h" //because of m_trackingGeometry-> in header
+#include "TrkExInterfaces/INavigator.h"  //using navigator. in this header
+#include <utility>
+#include <vector>
+#include <string>
+#include <memory>
+
+ namespace Trk{
+   class Surface;
+   class ExtrapolationCache;
+   class EnergyLoss;
+   class TransportJacobian;
+   class TrackStateOnSurface;
+ }
+ 
+namespace Trk{
+struct Cache
+  {
+    using TrackParmContainer = ObjContainer<Trk::TrackParameters>;
+    using ManagedTrackParmPtr = ObjPtr<Trk::TrackParameters>;
+    typedef std::vector<Trk::TrackParameters*> TrackParametersPtrVector;
+    typedef std::vector<std::pair<std::unique_ptr<Trk::TrackParameters>, int>> identifiedParameters_t;
+    using TrackParmPtr = ObjRef;
+    typedef std::pair<const Surface*, BoundaryCheck> DestSurf;
+    //
+    TrackParmContainer m_trackParmContainer;
+    //!< parameters to be used for final propagation in case of fallback
+    ManagedTrackParmPtr m_lastValidParameters;
+    //!< return helper for parameters and boundary
+    ParametersNextVolume m_parametersAtBoundary;
+    //!< Caches per MaterialUpdator
+    std::vector<Trk::IMaterialEffectsUpdator::ICache> m_MaterialUpCache;
+    //!<  internal switch for resolved configuration
+    bool m_dense = false;
+    //!< Flag the recall solution
+    bool m_recall = false;
+    bool m_robustSampling = true;
+    bool m_ownParametersOnDetElements = true;
+    unsigned int m_layerResolved{};
+    unsigned int m_methodSequence = 0;
+    const Surface* m_destinationSurface = nullptr;
+    //!< the boundary volume check
+    const Volume* m_boundaryVolume = nullptr;
+    //!< Destination Surface for recall
+    const Surface* m_recallSurface = nullptr;
+    //!< Destination Layer for recall
+    const Layer* m_recallLayer = nullptr;
+    //!< Destination TrackingVolume for recall
+    const TrackingVolume* m_recallTrackingVolume = nullptr;
+    const Trk::TrackingVolume* m_currentStatic = nullptr;
+    const Trk::TrackingVolume* m_currentDense = nullptr;
+    const Trk::TrackingVolume* m_highestVolume = nullptr;
+    //!< return helper for parameters on detector elements
+    TrackParametersPtrVector* m_parametersOnDetElements = nullptr;
+    //!< cache layer with last material update
+    const Layer* m_lastMaterialLayer = nullptr;
+    //!< cache for collecting the total X0 ans Eloss
+    Trk::ExtrapolationCache* m_extrapolationCache = nullptr;
+    //!< cache pointer for Eloss
+    const Trk::EnergyLoss* m_cacheEloss = nullptr;
+    //!< cache of TrackStateOnSurfaces
+    std::vector<const Trk::TrackStateOnSurface*>* m_matstates = nullptr;
+    //!< cache of Transport Jacobians
+    std::vector<Trk::TransportJacobian*>* m_jacs = nullptr;
+    // for active volumes
+    std::unique_ptr<identifiedParameters_t> m_identifiedParameters;
+
+    const Trk::TrackingGeometry *m_trackingGeometry = nullptr;
+    double m_path{};
+
+    std::pair<unsigned int, unsigned int> m_denseResolved;
+
+    std::vector<DestSurf> m_staticBoundaries;
+    std::vector<DestSurf> m_detachedBoundaries;
+    std::vector<DestSurf> m_denseBoundaries;
+    std::vector<DestSurf> m_navigBoundaries;
+    std::vector<DestSurf> m_layers;
+
+    std::vector<std::pair<const Trk::DetachedTrackingVolume*, unsigned int>> m_detachedVols;
+    std::vector<std::pair<const Trk::TrackingVolume*, unsigned int>> m_denseVols;
+    std::vector<std::pair<const Trk::TrackingVolume*, const Trk::Layer*>> m_navigLays;
+    std::vector<std::pair<const Trk::Surface*, Trk::BoundaryCheck>> m_navigSurfs;
+    std::vector<const Trk::DetachedTrackingVolume*> m_navigVols;
+    std::vector<std::pair<const Trk::TrackingVolume*, unsigned int>> m_navigVolsInt;
+    
+    //methods
+
+     Cache();
+     Cache(const std::vector<const IMaterialEffectsUpdator*> & updaters);
+    ~Cache();
+
+    TrackParmContainer& trackParmContainer() { return m_trackParmContainer; }
+
+ 
+    ManagedTrackParmPtr manage(std::unique_ptr<Trk::TrackParameters>&& parm)
+    {
+      return ManagedTrackParmPtr(trackParmContainer(), std::move(parm));
+    }
+    ManagedTrackParmPtr manage(TrackParmPtr parm)
+    {
+      return ManagedTrackParmPtr(trackParmContainer(), parm);
+    }
+    ManagedTrackParmPtr manage() { return ManagedTrackParmPtr(trackParmContainer()); }
+
+    const Trk::TrackingGeometry *trackingGeometry( const Trk::INavigator &navigator, const EventContext &ctx) {
+       if (!m_trackingGeometry) {
+          m_trackingGeometry = navigator.trackingGeometry(ctx);
+       }
+       return m_trackingGeometry;
+    }
+
+    const Trk::TrackingVolume 
+    *volume(const EventContext&, const Amg::Vector3D& gp) const {
+       assert(m_trackingGeometry);
+       return m_trackingGeometry->lowestTrackingVolume(gp);
+    }
+    
+
+   
+    
+     /** Get the IMaterialEffectsUpdator::ICache  for the MaterialEffectsUpdator*/
+    IMaterialEffectsUpdator::ICache& 
+    subMaterialEffectsUpdatorCache(const TrackingVolume& tvol) ;
+    
+    IMaterialEffectsUpdator::ICache& 
+    subMaterialEffectsUpdatorCache() ;
+    
+    //
+    void
+    populateMatEffUpdatorCache(const std::vector<const IMaterialEffectsUpdator*> & updaters);
+    
+     /** Private method for setting recall Information */
+    void 
+    setRecallInformation(const Surface&,const Layer&,const TrackingVolume&);
+    
+    void
+    resetRecallInformation();
+    
+    std::string 
+    to_string(const std::string& txt) const;
+    
+    std::string 
+    checkCache(const std::string& txt) const;
+    
+    bool
+    elossPointerOverwritten() const;
+    
+    
+
+    /**
+     * struct for accumulating stat counters
+     */
+    struct AtomicMax
+    {
+      void update(size_t val)
+      {
+        while (val > m_maxVal) {
+          val = m_maxVal.exchange(val);
+        }
+      }
+      size_t val() const { return m_maxVal; }
+      std::atomic<size_t> m_maxVal = 0;
+    };
+    static AtomicMax s_navigSurfsMax ATLAS_THREAD_SAFE;
+    static AtomicMax s_navigVolsMax ATLAS_THREAD_SAFE;
+    static AtomicMax s_navigVolsIntMax ATLAS_THREAD_SAFE;
+    static AtomicMax s_containerSizeMax ATLAS_THREAD_SAFE;
+    static bool s_reported ATLAS_THREAD_SAFE;
+  };
+  }
+  #endif
+  
+  
\ No newline at end of file
diff --git a/Tracking/TrkExtrapolation/TrkExTools/TrkExTools/ParametersNextVolume.h b/Tracking/TrkExtrapolation/TrkExTools/TrkExTools/ParametersNextVolume.h
new file mode 100644
index 0000000000000000000000000000000000000000..2f9f8e53649fd7deacf7b78e093d70e6a49607eb
--- /dev/null
+++ b/Tracking/TrkExtrapolation/TrkExTools/TrkExTools/ParametersNextVolume.h
@@ -0,0 +1,49 @@
+
+#ifndef TRKEXTOOLS_ParametersNextVolume_H
+#define TRKEXTOOLS_ParametersNextVolume_H
+
+#include "TrkGeometry/TrackingVolume.h" //for BoundarySurfaceFace
+#include "ObjContainer.h"
+#include "TrkParameters/TrackParameters.h"
+
+
+namespace Trk{
+  class TrackingGeometry;
+  
+  struct ParametersNextVolume{
+    using ManagedTrackParmPtr = ObjPtr<Trk::TrackParameters>;
+    using TrackParmContainer = ObjContainer<Trk::TrackParameters>;
+
+    //!< the members
+    const TrackingVolume* nextVolume;
+    ManagedTrackParmPtr nextParameters;
+    ManagedTrackParmPtr navParameters;
+    BoundarySurfaceFace exitFace;
+
+    ParametersNextVolume(TrackParmContainer& track_parm_container)
+      : nextVolume(nullptr)
+      , nextParameters(track_parm_container)
+      , navParameters(track_parm_container)
+      , exitFace(undefinedFace){
+    }
+
+    //!< update the boundaryInformation
+    void boundaryInformation(const TrackingVolume* tvol,
+                             ManagedTrackParmPtr nextPars,
+                             ManagedTrackParmPtr navPars,
+                             BoundarySurfaceFace face = undefinedFace){
+      nextVolume = tvol;
+      nextParameters = std::move(nextPars);
+      navParameters = std::move(navPars);
+      exitFace = face;
+    }
+    //!< reset the boundary information by invalidating it
+    void resetBoundaryInformation(){
+      nextVolume = nullptr;
+      exitFace = undefinedFace;
+      nextParameters = ManagedTrackParmPtr();
+      navParameters = ManagedTrackParmPtr();
+    }
+  };
+}
+#endif
\ No newline at end of file
diff --git a/Tracking/TrkExtrapolation/TrkExTools/src/Extrapolator.cxx b/Tracking/TrkExtrapolation/TrkExTools/src/Extrapolator.cxx
index bb6cf9dbdca5978c5bbcc79acb5ebf728d704d00..cb55f0e05938ba13d6e94ad5a7f9d36cfa9e5507 100755
--- a/Tracking/TrkExtrapolation/TrkExTools/src/Extrapolator.cxx
+++ b/Tracking/TrkExtrapolation/TrkExTools/src/Extrapolator.cxx
@@ -113,11 +113,11 @@ momentumOutput(const Amg::Vector3D& mom)
 
 } // end of anonymous namespace
 
-Trk::Extrapolator::Cache::AtomicMax Trk::Extrapolator::Cache::s_navigSurfsMax{};
-Trk::Extrapolator::Cache::AtomicMax Trk::Extrapolator::Cache::s_navigVolsMax{};
-Trk::Extrapolator::Cache::AtomicMax Trk::Extrapolator::Cache::s_navigVolsIntMax{};
-Trk::Extrapolator::Cache::AtomicMax Trk::Extrapolator::Cache::s_containerSizeMax{};
-bool Trk::Extrapolator::Cache::s_reported{};
+Trk::Cache::AtomicMax Trk::Cache::s_navigSurfsMax{};
+Trk::Cache::AtomicMax Trk::Cache::s_navigVolsMax{};
+Trk::Cache::AtomicMax Trk::Cache::s_navigVolsIntMax{};
+Trk::Cache::AtomicMax Trk::Cache::s_containerSizeMax{};
+bool Trk::Cache::s_reported{};
 
 // constructor
 Trk::Extrapolator::Extrapolator(const std::string& t, const std::string& n, const IInterface* p)
@@ -450,18 +450,18 @@ Trk::Extrapolator::finalize()
   }
   delete m_referenceSurface;
 
-  if (!Trk::Extrapolator::Cache::s_reported) {
-    Trk::Extrapolator::Cache::s_reported = true;
-    ATH_MSG_INFO("Trk::Extrapolator::Cache s_navigSurfsMax    = "
-                 << Trk::Extrapolator::Cache::s_navigSurfsMax.val());
-    ATH_MSG_INFO("Trk::Extrapolator::Cache s_navigSurfsMax    = "
-                 << Trk::Extrapolator::Cache::s_navigSurfsMax.val());
-    ATH_MSG_INFO("Trk::Extrapolator::Cache s_navigVolsMax     = "
-                 << Trk::Extrapolator::Cache::s_navigVolsMax.val());
-    ATH_MSG_INFO("Trk::Extrapolator::Cache s_navigVolsIntMax  = "
-                 << Trk::Extrapolator::Cache::s_navigVolsIntMax.val());
-    ATH_MSG_INFO("Trk::Extrapolator::Cache s_containerSizeMax = "
-                 << Trk::Extrapolator::Cache::s_containerSizeMax.val());
+  if (!Trk::Cache::s_reported) {
+    Trk::Cache::s_reported = true;
+    ATH_MSG_INFO("Trk::Cache s_navigSurfsMax    = "
+                 << Trk::Cache::s_navigSurfsMax.val());
+    ATH_MSG_INFO("Trk::Cache s_navigSurfsMax    = "
+                 << Trk::Cache::s_navigSurfsMax.val());
+    ATH_MSG_INFO("Trk::Cache s_navigVolsMax     = "
+                 << Trk::Cache::s_navigVolsMax.val());
+    ATH_MSG_INFO("Trk::Cache s_navigVolsIntMax  = "
+                 << Trk::Cache::s_navigVolsIntMax.val());
+    ATH_MSG_INFO("Trk::Cache s_containerSizeMax = "
+                 << Trk::Cache::s_containerSizeMax.val());
   }
 
   return StatusCode::SUCCESS;
@@ -532,7 +532,7 @@ Trk::Extrapolator::extrapolateStepwiseImpl(const EventContext& ctx,
   cache.m_parametersOnDetElements = &tmp;
   cache.m_ownParametersOnDetElements = true;
   // Material effect updator cache
-  populateMatEffUpdatorCache(cache);
+  cache.populateMatEffUpdatorCache(m_subupdaters);
   //TODO revisit when objcontainer is streamlined
   auto cloneInput = std::unique_ptr<Trk::TrackParameters>(parm.clone());
   // run the extrapolation
@@ -572,7 +572,7 @@ Trk::Extrapolator::extrapolateToNextActiveLayerImpl(const EventContext& ctx,
   ++cache.m_methodSequence;
   ATH_MSG_DEBUG("M-[" << cache.m_methodSequence << "] extrapolateToNextActiveLayer(...) ");
   // Material effect updator cache
-  populateMatEffUpdatorCache(cache);
+  cache.populateMatEffUpdatorCache(m_subupdaters);
   // initialize the return parameters vector
   //TODO revisit when objcontainer is streamlined
   auto cloneInput = std::unique_ptr<Trk::TrackParameters>(parm.clone());
@@ -642,7 +642,7 @@ Trk::Extrapolator::extrapolateToNextActiveLayerMImpl(
   ++cache.m_methodSequence;
   ATH_MSG_DEBUG("M-[" << cache.m_methodSequence << "] extrapolateToNextActiveLayerM(...) ");
   // Material effect updator cache
-  populateMatEffUpdatorCache(cache);
+  cache.populateMatEffUpdatorCache(m_subupdaters);
   // initialize the return parameters vector
   auto cloneInput = std::unique_ptr<Trk::TrackParameters>(parm.clone());
   ManagedTrackParmPtr currPar(cache.manage(std::move(cloneInput)));
@@ -899,9 +899,9 @@ Trk::Extrapolator::extrapolateToNextMaterialLayer(const EventContext& ctx,
     if (nextPar) {
       // collect material
       if (propagVol->zOverAtimesRho() != 0. && !cache.m_matstates && cache.m_extrapolationCache) {
-        if (checkCache(cache, " extrapolateToNextMaterialLayer")) {
+        if (cache.checkCache(" extrapolateToNextMaterialLayer").empty()) {
           if (m_dumpCache) {
-            dumpCache(cache, " extrapolateToNextMaterialLayer");
+            ATH_MSG_DEBUG(cache.to_string(" extrapolateToNextMaterialLayer"));
           }
           double dInX0 = fabs(path) / propagVol->x0();
           ATH_MSG_DEBUG(" add x0 " << dInX0);
@@ -916,7 +916,7 @@ Trk::Extrapolator::extrapolateToNextMaterialLayer(const EventContext& ctx,
           cache.m_extrapolationCache->updateEloss(
             eloss->meanIoni(), eloss->sigmaIoni(), eloss->meanRad(), eloss->sigmaRad());
           if (m_dumpCache) {
-            dumpCache(cache, " After");
+            ATH_MSG_DEBUG(cache.to_string( " After"));
           }
         }
       }
@@ -941,13 +941,13 @@ Trk::Extrapolator::extrapolateToNextMaterialLayer(const EventContext& ctx,
         //
        if (cache.m_extrapolationCache) {
           if (m_dumpCache) {
-            dumpCache(cache, " mat states extrapolateToNextMaterialLayer");
+            ATH_MSG_DEBUG(cache.to_string( " mat states extrapolateToNextMaterialLayer"));
           }
           cache.m_extrapolationCache->updateX0(dInX0);
           cache.m_extrapolationCache->updateEloss(
             eloss->meanIoni(), eloss->sigmaIoni(), eloss->meanRad(), eloss->sigmaRad());
           if (m_dumpCache) {
-            dumpCache(cache, " After");
+            ATH_MSG_DEBUG(cache.to_string( " After"));
           }
         }
         auto mefot =
@@ -1230,9 +1230,9 @@ Trk::Extrapolator::extrapolateToNextMaterialLayer(const EventContext& ctx,
       ATH_MSG_DEBUG("  [+] Number of intersection solutions: " << solutions.size());
       if (cache.m_currentDense->zOverAtimesRho() != 0. && !cache.m_matstates &&
           cache.m_extrapolationCache) {
-        if (checkCache(cache, " extrapolateToNextMaterialLayer dense")) {
+        if (cache.checkCache(" extrapolateToNextMaterialLayer dense").empty()) {
           if (m_dumpCache) {
-            dumpCache(cache, " extrapolateToNextMaterialLayer dense ");
+            ATH_MSG_DEBUG(cache.to_string( " extrapolateToNextMaterialLayer dense "));
           }
           double dInX0 = fabs(path) / cache.m_currentDense->x0();
           cache.m_extrapolationCache->updateX0(dInX0);
@@ -1243,7 +1243,7 @@ Trk::Extrapolator::extrapolateToNextMaterialLayer(const EventContext& ctx,
           cache.m_extrapolationCache->updateEloss(
             eloss->meanIoni(), eloss->sigmaIoni(), eloss->meanRad(), eloss->sigmaRad());
           if (m_dumpCache) {
-            dumpCache(cache, " After");
+            ATH_MSG_DEBUG(cache.to_string(" After"));
           }
         }
       }
@@ -1273,7 +1273,7 @@ Trk::Extrapolator::extrapolateToNextMaterialLayer(const EventContext& ctx,
 
         if (cache.m_extrapolationCache) {
           if (m_dumpCache) {
-            dumpCache(cache, " extrapolateToNextMaterialLayer dense");
+            ATH_MSG_DEBUG(cache.to_string(" extrapolateToNextMaterialLayer dense"));
           }
           cache.m_extrapolationCache->updateX0(dInX0);
           cache.m_extrapolationCache->updateEloss(eloss->meanIoni(),
@@ -1281,7 +1281,7 @@ Trk::Extrapolator::extrapolateToNextMaterialLayer(const EventContext& ctx,
                                                   eloss->meanRad(),
                                                   eloss->sigmaRad());
           if (m_dumpCache) {
-            dumpCache(cache, " After");
+             ATH_MSG_DEBUG(cache.to_string(" After"));
           }
         }
         auto mefot = std::make_unique<const Trk::MaterialEffectsOnTrack>(
@@ -1337,7 +1337,7 @@ Trk::Extrapolator::extrapolateToNextMaterialLayer(const EventContext& ctx,
               const IMaterialEffectsUpdator* currentUpdator =
                 subMaterialEffectsUpdator(*cache.m_currentStatic);
               IMaterialEffectsUpdator::ICache& currentUpdatorCache =
-                subMaterialEffectsUpdatorCache(cache, *cache.m_currentStatic);
+                cache.subMaterialEffectsUpdatorCache();
 
               if (currentUpdator) {
                 nextPar = cache.manage(
@@ -1372,10 +1372,10 @@ Trk::Extrapolator::extrapolateToNextMaterialLayer(const EventContext& ctx,
               }
 
               if (!cache.m_matstates && cache.m_extrapolationCache) {
-                if (checkCache(cache, " extrapolateToNextMaterialLayer thin")) {
+                if (cache.checkCache(" extrapolateToNextMaterialLayer thin").empty()) {
                   double dInX0 = thick / lx0;
                   if (m_dumpCache) {
-                    dumpCache(cache, " extrapolateToNextMaterialLayer thin ");
+                    ATH_MSG_DEBUG(cache.to_string(" extrapolateToNextMaterialLayer thin "));
                   }
                   cache.m_extrapolationCache->updateX0(dInX0);
                   double currentqoverp = nextPar->parameters()[Trk::qOverP];
@@ -1384,7 +1384,7 @@ Trk::Extrapolator::extrapolateToNextMaterialLayer(const EventContext& ctx,
                   cache.m_extrapolationCache->updateEloss(
                     eloss->meanIoni(), eloss->sigmaIoni(), eloss->meanRad(), eloss->sigmaRad());
                   if (m_dumpCache) {
-                    dumpCache(cache, " After");
+                     ATH_MSG_DEBUG(cache.to_string(" After"));
                   }
                 }
               }
@@ -1404,15 +1404,15 @@ Trk::Extrapolator::extrapolateToNextMaterialLayer(const EventContext& ctx,
                 std::unique_ptr<const Trk::TrackParameters> cvlTP(new Trk::CurvilinearParameters(
                   nextPar->position(), nextPar->momentum(), nextPar->charge()));
                if (cache.m_extrapolationCache) {
-                  if (checkCache(cache, " mat states extrapolateToNextMaterialLayer thin")) {
+                  if (cache.checkCache(" mat states extrapolateToNextMaterialLayer thin").empty()) {
                     if (m_dumpCache) {
-                      dumpCache(cache, " extrapolateToNextMaterialLayer thin");
+                      ATH_MSG_DEBUG(cache.to_string(" extrapolateToNextMaterialLayer thin "));
                     }
                     cache.m_extrapolationCache->updateX0(dInX0);
                     cache.m_extrapolationCache->updateEloss(
                       eloss->meanIoni(), eloss->sigmaIoni(), eloss->meanRad(), eloss->sigmaRad());
                     if (m_dumpCache) {
-                      dumpCache(cache, " After");
+                      ATH_MSG_DEBUG(cache.to_string(" After"));
                     }
                   }
                 }
@@ -1489,7 +1489,7 @@ Trk::Extrapolator::extrapolateToNextMaterialLayer(const EventContext& ctx,
             const IMaterialEffectsUpdator* currentUpdator =
               subMaterialEffectsUpdator(*cache.m_currentStatic);
             IMaterialEffectsUpdator::ICache& currentUpdatorCache =
-              subMaterialEffectsUpdatorCache(cache, *cache.m_currentStatic);
+              cache.subMaterialEffectsUpdatorCache();
 
             if (currentUpdator) {
               nextPar = cache.manage(
@@ -1522,10 +1522,10 @@ Trk::Extrapolator::extrapolateToNextMaterialLayer(const EventContext& ctx,
             }
 
             if (!cache.m_matstates && cache.m_extrapolationCache) {
-              if (checkCache(cache, " extrapolateToNextMaterialLayer thin")) {
+              if (cache.checkCache(" extrapolateToNextMaterialLayer thin").empty()) {
                 double dInX0 = thick / lx0;
                 if (m_dumpCache) {
-                  dumpCache(cache, " extrapolateToNextMaterialLayer thin ");
+                  ATH_MSG_DEBUG(cache.to_string(" extrapolateToNextMaterialLayer thin "));
                 }
                 cache.m_extrapolationCache->updateX0(dInX0);
                 Trk::MaterialProperties materialProperties(
@@ -1536,7 +1536,7 @@ Trk::Extrapolator::extrapolateToNextMaterialLayer(const EventContext& ctx,
                 cache.m_extrapolationCache->updateEloss(
                   eloss->meanIoni(), eloss->sigmaIoni(), eloss->meanRad(), eloss->sigmaRad());
                 if (m_dumpCache) {
-                  dumpCache(cache, " After");
+                  ATH_MSG_DEBUG(cache.to_string( " After"));
                 }
               }
             }
@@ -1558,15 +1558,15 @@ Trk::Extrapolator::extrapolateToNextMaterialLayer(const EventContext& ctx,
               std::unique_ptr<const Trk::TrackParameters> cvlTP(new Trk::CurvilinearParameters(
                 nextPar->position(), nextPar->momentum(), nextPar->charge()));
              if (cache.m_extrapolationCache) {
-                if (checkCache(cache, " mat states extrapolateToNextMaterialLayer thin")) {
+                if (cache.checkCache(" mat states extrapolateToNextMaterialLayer thin").empty()) {
                   if (m_dumpCache) {
-                    dumpCache(cache, " extrapolateToNextMaterialLayer thin");
+                    ATH_MSG_DEBUG(cache.to_string(" extrapolateToNextMaterialLayer thin "));
                   }
                   cache.m_extrapolationCache->updateX0(dInX0);
                   cache.m_extrapolationCache->updateEloss(
                     eloss->meanIoni(), eloss->sigmaIoni(), eloss->meanRad(), eloss->sigmaRad());
                   if (m_dumpCache) {
-                    dumpCache(cache, " After");
+                    ATH_MSG_DEBUG(cache.to_string( " After"));
                   }
                 }
               }
@@ -2094,7 +2094,7 @@ Trk::Extrapolator::extrapolateToVolumeImpl(const EventContext& ctx,
       //TODO revisit when objcontainer is streamlined
       auto cloneInput = std::unique_ptr<Trk::TrackParameters>(parm.clone());
       // Material effect updator cache
-      populateMatEffUpdatorCache(cache);
+      cache.populateMatEffUpdatorCache(m_subupdaters);
       returnParms = extrapolateImpl(ctx,
                                     cache,
                                     prop,
@@ -2123,7 +2123,7 @@ Trk::Extrapolator::extrapolateToVolumeImpl(const EventContext& ctx,
         //TODO revisit when objcontainer is streamlined
         auto cloneInput = std::unique_ptr<Trk::TrackParameters>(parm.clone());
         // Material effect updator cache
-        populateMatEffUpdatorCache(cache);
+        cache.populateMatEffUpdatorCache(m_subupdaters);
         returnParms = extrapolateImpl(ctx,
                                       cache,
                                       prop,
@@ -2163,7 +2163,7 @@ Trk::Extrapolator::extrapolate(const EventContext& ctx,
   // Material effect updator cache
   //TODO revisit when objcontainer is streamlined
   auto cloneInput = std::unique_ptr<Trk::TrackParameters>(parm.clone());
-  populateMatEffUpdatorCache(cache);
+  cache.populateMatEffUpdatorCache(m_subupdaters);
   return extrapolateImpl(ctx,
                          cache,
                          cache.manage(std::move(cloneInput)).index(),
@@ -2246,7 +2246,7 @@ Trk::Extrapolator::extrapolateBlindly(const EventContext& ctx,
       //TODO revisit when objcontainer is streamlined
       auto cloneInput = std::unique_ptr<Trk::TrackParameters>(parm.clone());
       // Material effect updator cache
-      populateMatEffUpdatorCache(cache);
+      cache.populateMatEffUpdatorCache(m_subupdaters);
       return extrapolateBlindlyImpl(ctx,
                                     cache,
                                     (*currentPropagator),
@@ -2382,7 +2382,7 @@ Trk::Extrapolator::extrapolateM(const EventContext& ctx,
 
   Cache cache{};
   // Material effect updator cache
-  populateMatEffUpdatorCache(cache);
+  cache.populateMatEffUpdatorCache(m_subupdaters);
   ATH_MSG_DEBUG("C-[" << cache.m_methodSequence << "] extrapolateM()");
   // create a new vector for the material to be collected
   cache.m_matstates = new std::vector<const Trk::TrackStateOnSurface*>;
@@ -3000,7 +3000,7 @@ Trk::Extrapolator::extrapolateImpl(const EventContext& ctx,
 
     const IMaterialEffectsUpdator* currentUpdator = subMaterialEffectsUpdator(tvol);
     IMaterialEffectsUpdator::ICache& currentUpdatorCache =
-      subMaterialEffectsUpdatorCache(cache, tvol);
+     cache.subMaterialEffectsUpdatorCache(tvol);
 
     ManagedTrackParmPtr upNext;
     if (currentUpdator) {
@@ -3036,7 +3036,7 @@ Trk::Extrapolator::extrapolateImpl(const EventContext& ctx,
                                                            << " cache.m_extrapolationCache "
                                                            << cache.m_extrapolationCache);
     if (cache.m_extrapolationCache) {
-      dumpCache(cache, " In extrapolate ");
+      ATH_MSG_DEBUG(cache.to_string(" In extrapolate "));
     }
   }
 
@@ -3491,7 +3491,7 @@ Trk::Extrapolator::insideVolumeStaticLayers(const EventContext& ctx,
 
       const IMaterialEffectsUpdator* currentUpdator = subMaterialEffectsUpdator(tvol);
       IMaterialEffectsUpdator::ICache& currentUpdatorCache =
-        subMaterialEffectsUpdatorCache(cache, tvol);
+        cache.subMaterialEffectsUpdatorCache(tvol);
 
       if (currentUpdator) {
         nextParameters = cache.manage(
@@ -3514,7 +3514,7 @@ Trk::Extrapolator::insideVolumeStaticLayers(const EventContext& ctx,
       } else {
         ATH_MSG_VERBOSE("  [-] Initial postUpdate killed track.");
         cache.m_parametersAtBoundary.resetBoundaryInformation();
-        resetRecallInformation(cache);
+        cache.resetRecallInformation();
         return {};
       }
     }
@@ -3547,14 +3547,14 @@ Trk::Extrapolator::insideVolumeStaticLayers(const EventContext& ctx,
         ATH_MSG_VERBOSE("  [+] Update may have killed track - return.");
         // set the new boundary information
         cache.m_parametersAtBoundary.resetBoundaryInformation();
-        resetRecallInformation(cache);
+        cache.resetRecallInformation();
         return {};
       } if (cache.m_boundaryVolume && nextParameters &&
                  !cache.m_boundaryVolume->inside(nextParameters->position())) {
         ATH_MSG_VERBOSE("  [+] Parameter outside the given boundary/world stopping loop.");
         // set the new boundary information
         cache.m_parametersAtBoundary.resetBoundaryInformation();
-        resetRecallInformation(cache);
+        cache.resetRecallInformation();
         return {};
       }
       // --------------------------------------------------------
@@ -3619,14 +3619,14 @@ Trk::Extrapolator::insideVolumeStaticLayers(const EventContext& ctx,
         ATH_MSG_VERBOSE("  [+] Update may have killed track - return.");
         // set the new boundary information
         cache.m_parametersAtBoundary.resetBoundaryInformation();
-        resetRecallInformation(cache);
+        cache.resetRecallInformation();
         return {};
       } if (cache.m_boundaryVolume && updateNext &&
                  !cache.m_boundaryVolume->inside(updateNext->position())) {
         ATH_MSG_VERBOSE("  [+] Parameter outside the given boundary/world stopping loop.");
         // set the new boundary information
         cache.m_parametersAtBoundary.resetBoundaryInformation();
-        resetRecallInformation(cache);
+        cache.resetRecallInformation();
         return {};
       }
       // the fallback if only one step was done - solve cleaner
@@ -3651,7 +3651,7 @@ Trk::Extrapolator::insideVolumeStaticLayers(const EventContext& ctx,
                                                      matupmode);
 
       // set the recallInformation <- everything went fine
-      setRecallInformation(cache, *cache.m_destinationSurface, *destinationLayer, tvol);
+      cache.setRecallInformation( *cache.m_destinationSurface, *destinationLayer, tvol);
       // done
       return nextParameters;
     }
@@ -3668,7 +3668,7 @@ Trk::Extrapolator::insideVolumeStaticLayers(const EventContext& ctx,
                                                   particle));
     // job done: cleanup and go home
     // reset the recallInformation
-    resetRecallInformation(cache);
+    cache.resetRecallInformation();
     // return the directly extrapolated ones
     return nextParameters;
   }
@@ -3744,7 +3744,7 @@ Trk::Extrapolator::insideVolumeStaticLayers(const EventContext& ctx,
       ATH_MSG_VERBOSE("    Starting Parameters not defined.");
     }
     // reset the recall information as it is invalid
-    resetRecallInformation(cache);
+    cache.resetRecallInformation();
   }
 
   if (bParameters && bParameters->associatedSurface().materialLayer()) {
@@ -3753,7 +3753,7 @@ Trk::Extrapolator::insideVolumeStaticLayers(const EventContext& ctx,
 
       const IMaterialEffectsUpdator* currentUpdator = m_subupdaters[tvol.geometrySignature()];
       IMaterialEffectsUpdator::ICache& currentUpdatorCache =
-        subMaterialEffectsUpdatorCache(cache, tvol);
+        cache.subMaterialEffectsUpdatorCache(tvol);
 
       if (currentUpdator) {
         bParameters = cache.manage(currentUpdator->update(
@@ -3974,7 +3974,7 @@ Trk::Extrapolator::extrapolateToDestinationLayer(const EventContext& ctx,
   // return the pre-updated ones
   const IMaterialEffectsUpdator* currentUpdator = subMaterialEffectsUpdator(tvol);
   IMaterialEffectsUpdator::ICache& currentUpdatorCache =
-    subMaterialEffectsUpdatorCache(cache, tvol);
+    cache.subMaterialEffectsUpdatorCache(tvol);
 
   ManagedTrackParmPtr preUpdatedParameters(cache.manage());
   if (currentUpdator && destParameters && !startIsDestLayer) {
@@ -4044,7 +4044,7 @@ Trk::Extrapolator::extrapolateToIntermediateLayer(const EventContext& ctx,
   // chose the current updator
   const IMaterialEffectsUpdator* currentUpdator = subMaterialEffectsUpdator(tvol);
   IMaterialEffectsUpdator::ICache& currentUpdatorCache =
-    subMaterialEffectsUpdatorCache(cache, tvol);
+    cache.subMaterialEffectsUpdatorCache(tvol);
   // then go onto the Layer
   ManagedTrackParmPtr parm(cache.manage(parm_ref));
   ManagedTrackParmPtr parsOnLayer(cache.trackParmContainer());
@@ -4380,7 +4380,7 @@ Trk::Extrapolator::initializeNavigation(const EventContext& ctx,
       // 3 - GLOBAL SEARCH METHOD
       ++m_startThroughGlobalSearch;
       // non-perigee surface
-      resetRecallInformation(cache);
+      cache.resetRecallInformation();
       associatedVolume = cache.volume(ctx,parm->position());
 
       associatedLayer =
@@ -4654,7 +4654,7 @@ Trk::Extrapolator::addMaterialEffectsOnTrack(const EventContext& ctx,
     if (cache.m_extrapolationCache) {
       double tInX0 = pathCorrection * materialProperties->thicknessInX0();
       if (m_dumpCache) {
-        dumpCache(cache, " addMaterialEffectsOnTrack");
+        ATH_MSG_DEBUG(cache.to_string(" addMaterialEffectsOnTrack"));
       }
       cache.m_extrapolationCache->updateX0(tInX0);
       double currentQoP = parsOnLayer->parameters()[Trk::qOverP];
@@ -4665,7 +4665,7 @@ Trk::Extrapolator::addMaterialEffectsOnTrack(const EventContext& ctx,
                                               energyLoss->meanRad(),
                                               energyLoss->sigmaRad());
       if (m_dumpCache) {
-        dumpCache(cache, " After");
+        ATH_MSG_DEBUG(cache.to_string(" After"));
       }
     }
     ATH_MSG_VERBOSE("  [V] Validation mode: MaterialProperties found on this layer.");
@@ -4690,7 +4690,7 @@ Trk::Extrapolator::addMaterialEffectsOnTrack(const EventContext& ctx,
                         "switch joboption DetailedEloss on ");
       }
       if (m_dumpCache) {
-        dumpCache(cache, " addMaterialEffectsOnTrack");
+        ATH_MSG_DEBUG(cache.to_string(" addMaterialEffectsOnTrack"));
       }
       cache.m_extrapolationCache->updateX0(tInX0);
       cache.m_extrapolationCache->updateEloss(energyLoss->meanIoni(),
@@ -4698,7 +4698,7 @@ Trk::Extrapolator::addMaterialEffectsOnTrack(const EventContext& ctx,
                                               energyLoss->meanRad(),
                                               energyLoss->sigmaRad());
       if (m_dumpCache) {
-        dumpCache(cache, " After");
+        ATH_MSG_DEBUG(cache.to_string(" After"));
       }
     }
     auto meot = std::make_unique<const Trk::MaterialEffectsOnTrack>(
@@ -4710,36 +4710,8 @@ Trk::Extrapolator::addMaterialEffectsOnTrack(const EventContext& ctx,
   }
 }
 
-void
-Trk::Extrapolator::dumpCache(Cache& cache, const std::string& txt) const
-{
-  if (cache.m_cacheEloss != nullptr && cache.m_cacheEloss != cache.m_extrapolationCache->eloss()) {
-    ATH_MSG_DEBUG(" NO dumpCache: Eloss cache pointer overwritten "
-                  << cache.m_cacheEloss << " from extrapolationCache "
-                  << cache.m_extrapolationCache->eloss());
-    return;
-  }
-
-  ATH_MSG_DEBUG(txt << " X0 " << cache.m_extrapolationCache->x0tot() << " Eloss deltaE "
-                    << cache.m_extrapolationCache->eloss()->deltaE() << " Eloss sigma "
-                    << cache.m_extrapolationCache->eloss()->sigmaDeltaE() << " meanIoni "
-                    << cache.m_extrapolationCache->eloss()->meanIoni() << " sigmaIoni "
-                    << cache.m_extrapolationCache->eloss()->sigmaIoni() << " meanRad "
-                    << cache.m_extrapolationCache->eloss()->meanRad() << " sigmaRad "
-                    << cache.m_extrapolationCache->eloss()->sigmaRad());
-}
 
-bool
-Trk::Extrapolator::checkCache(Cache& cache, const std::string& txt) const
-{
-  if (cache.m_cacheEloss != nullptr && cache.m_cacheEloss != cache.m_extrapolationCache->eloss()) {
-    ATH_MSG_DEBUG(txt << " PROBLEM Eloss cache pointer overwritten " << cache.m_cacheEloss
-                      << " from extrapolationCache " << cache.m_extrapolationCache->eloss());
-    return false;
-  }
-    return true;
 
-}
 
 std::unique_ptr<std::vector<std::pair<std::unique_ptr<Trk::TrackParameters>, int>>>
 Trk::Extrapolator::extrapolate(const EventContext& ctx,
@@ -4768,7 +4740,7 @@ Trk::Extrapolator::extrapolate(const EventContext& ctx,
   // cleanup
   cache.m_parametersAtBoundary.resetBoundaryInformation();
   // Material effect updator cache
-  populateMatEffUpdatorCache(cache);
+  cache.populateMatEffUpdatorCache(m_subupdaters);
   // extrapolate to subdetector boundary
   //TODO revisit when objcontainer is streamlined
   auto cloneInput = std::unique_ptr<Trk::TrackParameters>(parm.clone());
@@ -4842,7 +4814,7 @@ Trk::Extrapolator::extrapolateWithPathLimit(const EventContext& ctx,
   // cleanup
   cache.m_parametersAtBoundary.resetBoundaryInformation();
   // Material effect updator cache
-  populateMatEffUpdatorCache(cache);
+  cache.populateMatEffUpdatorCache(m_subupdaters);
 
   // if no input volume, define as highest volume
   // const Trk::TrackingVolume* destVolume = boundaryVol ? boundaryVol :
@@ -5383,13 +5355,13 @@ Trk::Extrapolator::extrapolateToVolumeWithPathLimit(const EventContext& ctx,
       std::unique_ptr<EnergyLoss> eloss = (m_elossupdaters[0]->energyLoss(
         materialProperties, fabs(1. / currentqoverp), 1., dir, particle));
       if (m_dumpCache) {
-        dumpCache(cache, " extrapolateToVolumeWithPathLimit");
+        ATH_MSG_DEBUG(cache.to_string( " extrapolateToVolumeWithPathLimit"));
       }
       cache.m_extrapolationCache->updateX0(dInX0);
       cache.m_extrapolationCache->updateEloss(
         eloss->meanIoni(), eloss->sigmaIoni(), eloss->meanRad(), eloss->sigmaRad());
       if (m_dumpCache) {
-        dumpCache(cache, " After");
+        ATH_MSG_DEBUG(cache.to_string(" After"));
       }
     }
     if (cache.m_currentDense->zOverAtimesRho() != 0. && cache.m_matstates) {
@@ -5410,13 +5382,13 @@ Trk::Extrapolator::extrapolateToVolumeWithPathLimit(const EventContext& ctx,
 
      if (cache.m_extrapolationCache) {
         if (m_dumpCache) {
-          dumpCache(cache, " extrapolateToVolumeWithPathLimit");
+          ATH_MSG_DEBUG(cache.to_string(" extrapolateToVolumeWithPathLimit"));
         }
         cache.m_extrapolationCache->updateX0(dInX0);
         cache.m_extrapolationCache->updateEloss(
           eloss->meanIoni(), eloss->sigmaIoni(), eloss->meanRad(), eloss->sigmaRad());
         if (m_dumpCache) {
-          dumpCache(cache, " After");
+          ATH_MSG_DEBUG(cache.to_string( " After"));
         }
       }
       auto mefot = std::make_unique<const Trk::MaterialEffectsOnTrack>(
@@ -5444,7 +5416,7 @@ Trk::Extrapolator::extrapolateToVolumeWithPathLimit(const EventContext& ctx,
             const IMaterialEffectsUpdator* currentUpdator =
               subMaterialEffectsUpdator(*cache.m_currentStatic);
             IMaterialEffectsUpdator::ICache& currentUpdatorCache =
-              subMaterialEffectsUpdatorCache(cache, *cache.m_currentStatic);
+              cache.subMaterialEffectsUpdatorCache();
             if (currentUpdator) {
               nextPar = cache.manage(
                 currentUpdator->update(
@@ -5532,7 +5504,7 @@ Trk::Extrapolator::extrapolateToVolumeWithPathLimit(const EventContext& ctx,
         const IMaterialEffectsUpdator* currentUpdator =
           subMaterialEffectsUpdator(*cache.m_currentStatic);
         IMaterialEffectsUpdator::ICache& currentUpdatorCache =
-          subMaterialEffectsUpdatorCache(cache, *cache.m_currentStatic);
+          cache.subMaterialEffectsUpdatorCache();
 
         if (matUp && nextLayer->surfaceArray()) {
           double pIn = nextPar->momentum().mag();
diff --git a/Tracking/TrkExtrapolation/TrkExTools/src/LocalExtrapolatorCache.cxx b/Tracking/TrkExtrapolation/TrkExTools/src/LocalExtrapolatorCache.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..fc2daae082b82cb17f2dcda76097060816d13e26
--- /dev/null
+++ b/Tracking/TrkExtrapolation/TrkExTools/src/LocalExtrapolatorCache.cxx
@@ -0,0 +1,118 @@
+/*
+   Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
+ */
+#include "TrkSurfaces/Surface.h"
+#include "TrkExUtils/ExtrapolationCache.h" 
+#include "TrkExTools/LocalExtrapolatorCache.h"
+
+
+namespace Trk{
+
+  Cache::Cache()
+      : m_trackParmContainer(128)
+      , // always reserve some space; still occasionally more slots are
+        // needed; above 150 there are very few cases the max in q431 was 257
+      m_lastValidParameters(m_trackParmContainer)
+      , m_parametersAtBoundary(m_trackParmContainer)
+    {
+      m_navigSurfs.reserve(1024);
+      m_navigVols.reserve(64);
+      m_navigVolsInt.reserve(64);
+    }
+    
+  Cache::Cache(const std::vector<const IMaterialEffectsUpdator*> & updaters)
+  : m_trackParmContainer(128), m_lastValidParameters(m_trackParmContainer),
+   m_parametersAtBoundary(m_trackParmContainer){
+    m_navigSurfs.reserve(1024);
+    m_navigVols.reserve(64);
+    m_navigVolsInt.reserve(64);
+    populateMatEffUpdatorCache(updaters);
+  }
+    
+    Cache::~Cache()
+    {
+      s_navigSurfsMax.update(m_navigSurfs.size());
+      s_navigVolsMax.update(m_navigVols.size());
+      s_navigVolsIntMax.update(m_navigVols.size());
+      if (m_ownParametersOnDetElements && m_parametersOnDetElements) {
+        for (const Trk::TrackParameters* parm : *m_parametersOnDetElements) {
+          delete parm;
+        }
+      }
+      s_containerSizeMax.update(trackParmContainer().size());
+    }
+
+
+
+  IMaterialEffectsUpdator::ICache&
+  Cache::subMaterialEffectsUpdatorCache( const TrackingVolume& tvol){
+    return m_MaterialUpCache[tvol.geometrySignature()];
+  }
+  
+  IMaterialEffectsUpdator::ICache&
+  Cache::subMaterialEffectsUpdatorCache() {
+    return m_MaterialUpCache[m_currentStatic->geometrySignature()];
+  }
+  
+  void
+  Cache::populateMatEffUpdatorCache(const std::vector<const IMaterialEffectsUpdator*> & updaters) {
+    size_t numUpdaters = updaters.size();
+    m_MaterialUpCache.reserve(numUpdaters);
+    for (const auto & thisUpdater : updaters) {
+      m_MaterialUpCache.emplace_back(thisUpdater->getCache());
+    }
+  }
+  
+  void
+  Cache::setRecallInformation(const Surface& rsf,const Layer& rlay,const TrackingVolume& rvol) {
+    m_recall = true;
+    m_recallSurface = &rsf;
+    m_recallLayer = &rlay;
+    m_recallTrackingVolume = &rvol;
+  }
+  
+  void
+  Cache::resetRecallInformation() {
+    m_recall = false;
+    m_recallSurface = nullptr;
+    m_recallLayer = nullptr;
+    m_recallTrackingVolume = nullptr;
+  }
+  
+  std::string 
+  Cache::to_string(const std::string& txt) const{
+    std::string result;
+    if (elossPointerOverwritten()) {
+      result = " NO dumpCache: Eloss cache pointer overwritten "
+                    + std::to_string(reinterpret_cast<std::uintptr_t>(m_cacheEloss)) + " from extrapolationCache "
+                    + std::to_string(reinterpret_cast<std::uintptr_t>(m_extrapolationCache->eloss()));
+    } else {
+      result = txt + " X0 " +std::to_string(m_extrapolationCache->x0tot())  + " Eloss deltaE "
+                      + std::to_string(m_extrapolationCache->eloss()->deltaE()) + " Eloss sigma "
+                      +  std::to_string(m_extrapolationCache->eloss()->sigmaDeltaE()) + " meanIoni "
+                      + std::to_string(m_extrapolationCache->eloss()->meanIoni()) + " sigmaIoni "
+                      + std::to_string(m_extrapolationCache->eloss()->sigmaIoni()) + " meanRad "
+                      + std::to_string(m_extrapolationCache->eloss()->meanRad()) + " sigmaRad "
+                      + std::to_string(m_extrapolationCache->eloss()->sigmaRad());
+    }
+    return result;
+  }
+  
+  std::string
+  Cache::checkCache(const std::string& txt) const{
+    std::string result;
+    if (elossPointerOverwritten()) {
+      result = txt + " PROBLEM Eloss cache pointer overwritten " + std::to_string(reinterpret_cast<std::uintptr_t>(m_cacheEloss))
+                        + " from extrapolationCache " + std::to_string(reinterpret_cast<std::uintptr_t>(m_extrapolationCache->eloss()));
+    }
+    return result;
+  }
+  
+  bool
+  Cache::elossPointerOverwritten() const{
+    return (m_cacheEloss != nullptr && m_cacheEloss != m_extrapolationCache->eloss());
+  }
+
+
+
+}
\ No newline at end of file