diff --git a/Tracking/TrkExtrapolation/TrkExEngine/TrkExEngine/ExtrapolationEngine.h b/Tracking/TrkExtrapolation/TrkExEngine/TrkExEngine/ExtrapolationEngine.h
new file mode 100644
index 0000000000000000000000000000000000000000..1ce41acc943f6b058fb5778d12b257fd10aa69d0
--- /dev/null
+++ b/Tracking/TrkExtrapolation/TrkExEngine/TrkExEngine/ExtrapolationEngine.h
@@ -0,0 +1,130 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// ExtrapolationEngine.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef TRKEXINTERFACES_EXTRAPOLATIONENGINE_H
+#define TRKEXINTERFACES_EXTRAPOLATIONENGINE_H
+
+// Gaudi
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "GaudiKernel/ServiceHandle.h"
+// Trk
+#include "TrkDetDescrInterfaces/ITrackingGeometrySvc.h"
+#include "TrkExInterfaces/IExtrapolationEngine.h"
+#include "TrkExEngine/ExtrapolationMacros.h"
+#include "TrkExUtils/ExtrapolationCell.h"
+#include "TrkParameters/TrackParameters.h"
+#include "TrkNeutralParameters/NeutralParameters.h"
+// throw GaudiExceptions where necessary
+#include "GaudiKernel/GaudiException.h"
+
+namespace Trk {
+  
+  class TrackingGeometry;
+  
+  /** @class ExtrapolationEngine 
+      
+      Master extrapolation engine for extrapolation through the TrackingGeometry,
+      it delegates the extrapolation to optimised engines, handing over the ExtrapolationCell
+      as internal cache.
+  
+      There are identical interfaces for charged and neutral track parameters.
+      Providing a destination surface is optional, if no destination surface is given the extrapolation 
+      process can be stopped by other directives, e.g. stopping at a certain path limit, material limit
+      or with a change of detector signature.
+  
+      @author Andreas.Salzburger -at- cern.ch 
+  */
+  class ExtrapolationEngine : public AthAlgTool, virtual public IExtrapolationEngine {
+      
+      friend class NavigationInitTest;
+      
+      public:
+        /** Constructor */
+        ExtrapolationEngine(const std::string&,const std::string&,const IInterface*);
+        
+        /** Destructor */
+        ~ExtrapolationEngine();
+
+        /** AlgTool initialize method */
+        StatusCode initialize();
+        
+        /** AlgTool finalize method */
+        StatusCode finalize();
+        
+        using IExtrapolationEngine::extrapolate;
+        
+        /** charged extrapolation - public interface */
+        virtual ExtrapolationCode extrapolate(ExCellCharged& ecCharged,
+                                              const Surface* sf = 0,
+                                              PropDirection dir=alongMomentum,
+                                              BoundaryCheck bcheck = true) const;
+
+        /** neutral extrapolation - public interface */
+        virtual ExtrapolationCode extrapolate(ExCellNeutral& ecNeutral,
+                                              const Surface* sf = 0,
+                                              PropDirection dir=alongMomentum,
+                                              BoundaryCheck bcheck = true) const;
+                         
+                         
+        /** define for which GeometrySignature this extrapolator is valid - this is GLOBAL */
+        GeometryType geometryType() const;                           
+                         
+     private:
+        /** main loop extrapolation method */
+        template <class T> ExtrapolationCode extrapolateT(ExtrapolationCell<T>& eCell,
+                                                          const Surface* sf = 0,
+                                                          PropDirection dir=alongMomentum,
+                                                          BoundaryCheck bcheck = true) const;
+            
+        /** initialization method */                                      
+        template <class T>  ExtrapolationCode initNavigation(ExtrapolationCell<T>& eCell,
+                                                             const Surface* sf = 0,
+                                                             PropDirection dir=alongMomentum) const throw (GaudiException);
+                
+                
+        //!< retrieve TrackingGeometry
+        StatusCode  updateTrackingGeometry() const; 
+
+        //!< return and retrieve
+        const TrackingGeometry& trackingGeometry() const throw (GaudiException);
+
+        mutable const TrackingGeometry*                     m_trackingGeometry;          //!< the tracking geometry owned by the navigator
+        ServiceHandle<ITrackingGeometrySvc>                 m_trackingGeometrySvc;       //!< ToolHandle to the TrackingGeometrySvc
+        std::string                                         m_trackingGeometryName;      //!< Name of the TrackingGeometry as given in Detector Store
+        
+        //!< the tool handle array for static / dense / detached
+        ToolHandleArray<IExtrapolationEngine>               m_extrapolationEngines;
+        std::vector<const IExtrapolationEngine*>            m_eeAccessor;     
+                                             
+        //!< forces a global search for the initialization, allows to switch TrackingGeometries in one job
+        bool                                                m_forceSearchInit; 
+    
+    };
+
+  inline GeometryType  ExtrapolationEngine::geometryType() const 
+      { return Trk::Master; }
+
+
+  inline const Trk::TrackingGeometry& ExtrapolationEngine::trackingGeometry() const throw (GaudiException) {
+      if (!m_trackingGeometry && updateTrackingGeometry().isFailure()){
+          ATH_MSG_ERROR("Could not load TrackingGeometry with name '" << m_trackingGeometryName << "'. Aborting." );
+          throw GaudiException("ExtrapolationEngine", "Problem with TrackingGeometry loading.", StatusCode::FAILURE);
+      }
+      return (*m_trackingGeometry);
+  }
+   
+   
+
+} // end of namespace
+
+//!< define the templated function    
+#include "ExtrapolationEngine.icc"  
+
+#endif // TRKEXINTERFACES_IEXTRAPOLATIONENGINE_H
+
diff --git a/Tracking/TrkExtrapolation/TrkExEngine/TrkExEngine/ExtrapolationEngine.icc b/Tracking/TrkExtrapolation/TrkExEngine/TrkExEngine/ExtrapolationEngine.icc
new file mode 100644
index 0000000000000000000000000000000000000000..5eb5ce6b79255edfacaecd2693cd3442e80cd921
--- /dev/null
+++ b/Tracking/TrkExtrapolation/TrkExEngine/TrkExEngine/ExtrapolationEngine.icc
@@ -0,0 +1,106 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// ExtrapolationEngine.icc, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#include "TrkSurfaces/Surface.h"
+#include "TrkVolumes/BoundarySurface.h"
+#include "TrkGeometry/TrackingGeometry.h"
+#include "TrkGeometry/TrackingVolume.h"
+#include "TrkGeometry/Layer.h"
+#include <iostream>
+#include <iomanip>
+
+template <class T> Trk::ExtrapolationCode Trk::ExtrapolationEngine::extrapolateT(Trk::ExtrapolationCell<T>& eCell,
+                                                                                 const Trk::Surface* sf,
+                                                                                 Trk::PropDirection dir,
+                                                                                 Trk::BoundaryCheck bcheck) const
+{
+                                                              
+    EX_MSG_DEBUG(++eCell.navigationStep, "starting extrapolation sequence."); 
+    // initialize the navigation
+    Trk::ExtrapolationCode eCode = initNavigation<T>(eCell,sf,dir);
+    EX_MSG_VERBOSE(eCell.navigationStep, "initialize navigation return code : " << eCode.toString() );
+    // main loop over volumes 
+    while (eCell.leadVolume && eCode == Trk::ExtrapolationCode::InProgress ){
+        // get the appropriate IExtrapolationEngine
+        const Trk::IExtrapolationEngine* iee = m_eeAccessor[eCell.leadVolume->geometryType()];
+        eCode = iee ? iee->extrapolate(eCell, sf, dir, bcheck) : Trk::ExtrapolationCode::FailureConfiguration;
+        // give a message about what you have
+        EX_MSG_VERBOSE(eCell.navigationStep, "returned from volume return code : " << eCode.toString() );
+    }
+    EX_MSG_DEBUG(eCell.navigationStep, "extrapolation finished return code : " << eCode.toString() );
+    // before you return, finalize: sets the leadParameters to endParameters and empties the garbage bin
+    eCell.finalize(eCode);
+    // return the code                                                               
+    return eCode;                                                               
+}
+                                                          
+                                                          
+template <class T> Trk::ExtrapolationCode Trk::ExtrapolationEngine::initNavigation(Trk::ExtrapolationCell<T>& eCell,
+                                                                                   const Trk::Surface* sf,
+                                                                                   Trk::PropDirection dir) const throw (GaudiException)
+{
+    // initialize the Navigation stream ----------------------------------------------------------------------------------------
+    //
+    // this is the global initialization, it only associated direct objects
+    // detailed navigation search needs to be done by the sub engines (since they know best)
+    EX_MSG_DEBUG(++eCell.navigationStep, "initialize the navigation stream."); 
+    if (!m_trackingGeometry && updateTrackingGeometry().isFailure()){
+	    EX_MSG_WARNING(eCell.navigationStep, "could not retrieve TrackingGeometry. Stopping."); 
+            return Trk::ExtrapolationCode::FailureConfiguration;
+    } else
+      EX_MSG_DEBUG("navi", "successfully retrieved TrackingGeometry.");    
+    // ---------- START initialization -----------------------------------------------------------------------------------------
+    // initialize the start parameters - try association first
+    eCell.startLayer  = eCell.startLayer ? eCell.startLayer : eCell.leadParameters->associatedSurface().associatedLayer();
+    eCell.startVolume = eCell.startVolume ? eCell.startVolume :
+        ( eCell.startLayer ? eCell.startLayer->enclosingTrackingVolume() : m_trackingGeometry->lowestTrackingVolume(eCell.leadParameters->position()) );
+    // bail out of the start volume can not be resolved
+    if (!eCell.startVolume) return Trk::ExtrapolationCode::FailureNavigation;
+    // screen output
+    EX_MSG_VERBOSE( eCell.navigationStep, "start volume termined as '" << eCell.startVolume->volumeName() << "'." );
+    // check if the parameters are on a volume boundary - @TODO identify this case by something like eCell.leadParameters->associatedSurface().isBoundary()
+    if ( eCell.startVolume->onVolumeBoundary(*eCell.startParameters) ){
+        // re-evaluate the volume by stepping out of the volume
+        EX_MSG_VERBOSE( eCell.navigationStep, "parameters are on volume boundary, stepping out of this TrackingVolume." );
+        // stepping by one unit out of the volume
+        eCell.startVolume = m_trackingGeometry->lowestTrackingVolume(eCell.leadParameters->position()+dir*eCell.leadParameters->momentum().unit());
+        // 
+        EX_MSG_VERBOSE( eCell.navigationStep, "start volume re-evaluated as '" << eCell.startVolume->volumeName() << "'." );
+    }
+    eCell.startLayer     = eCell.startLayer ? eCell.startLayer : eCell.startVolume->associatedLayer(eCell.leadParameters->position());
+    // now you can assign the lead volume    
+    eCell.leadVolume     = eCell.startVolume;  
+    // ---------- END initialization -----------------------------------------------------------------------------------------
+    if (sf){
+      // keep track of the end surface    
+      eCell.endSurface = sf;
+      // trying association via the layer : associated layer of material layer 
+      eCell.endLayer  = sf ? ( sf->associatedLayer() ? sf->associatedLayer() : sf->materialLayer() ) : 0;    
+      eCell.endVolume = eCell.endLayer ? eCell.endLayer->enclosingTrackingVolume() : 0;
+      // check if you found layer and volume
+      if (!eCell.endVolume){
+          EX_MSG_VERBOSE( eCell.navigationStep, "end volume needs to be determinded by surface intersection." );
+          // make a straight line intersection
+          Trk::Intersection sfI = (dir == Trk::alongMomentum) ?
+                 sf->straightLineIntersection(eCell.leadParameters->position(), eCell.leadParameters->momentum().unit(), true) :
+                 sf->straightLineIntersection(eCell.leadParameters->position(), -1*(eCell.leadParameters->momentum().unit()), true);
+          // use this to find endVolume and endLayer
+          eCell.endVolume = trackingGeometry().lowestTrackingVolume(sfI.position);                 
+          eCell.endLayer  = eCell.endLayer ? eCell.endLayer : trackingGeometry().associatedLayer(sfI.position);
+      } 
+      // check the final end volume configuraiton - screen output
+      if (eCell.endVolume)
+          EX_MSG_VERBOSE( eCell.navigationStep, "end volume termined as '" << eCell.endVolume->volumeName() << "'." );
+    } else 
+        EX_MSG_VERBOSE( eCell.navigationStep, "no destination surface nor end volume provided, extrapolaiton has to stop on other means." );
+    // return the progress call
+    return Trk::ExtrapolationCode::InProgress;                                                          
+                                                              
+}
+                                                          
+                                                          
diff --git a/Tracking/TrkExtrapolation/TrkExEngine/TrkExEngine/ExtrapolationMacros.h b/Tracking/TrkExtrapolation/TrkExEngine/TrkExEngine/ExtrapolationMacros.h
new file mode 100644
index 0000000000000000000000000000000000000000..bf1ab8d5e550368895dcbf18be0dfa06011fea7c
--- /dev/null
+++ b/Tracking/TrkExtrapolation/TrkExEngine/TrkExEngine/ExtrapolationMacros.h
@@ -0,0 +1,29 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// IExtrapolationMacros.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+
+#ifndef EXSCREENOUTPUTDEFS
+#define EXSCREENOUTPUTDEFS 1
+#define EX_MSG_INFO(nav, x)    ATH_MSG_INFO(m_sopPrefix << std::setw(4) << nav << m_sopPostfix << x)
+#define EX_MSG_DEBUG(nav, x)   ATH_MSG_DEBUG(m_sopPrefix << std::setw(4) << nav << m_sopPostfix << x)
+#define EX_MSG_VERBOSE(nav, x) ATH_MSG_VERBOSE(m_sopPrefix << std::setw(4) << nav << m_sopPostfix << x)
+#define EX_MSG_WARNING(nav, x) ATH_MSG_WARNING(m_sopPrefix << std::setw(4) << nav << m_sopPostfix << x)
+#define EX_MSG_FATAL(nav, x)   ATH_MSG_FATAL(m_sopPrefix << std::setw(4) << nav << m_sopPostfix << x)
+#endif
+
+#ifndef TRKEXENINGE_OUTPUTHELPER 
+#define TRKEXENINGE_OUTPUTHELPER 
+#define OH_CHECKFOUND(object) ( object ? "found" : "not found")
+#endif
+
+#ifndef TRKEXENGINE_EXCODECHECKS
+#define TRKEXENGINE_EXCODECHECKS
+#define CHECK_ECODE_CONTINUE(ecell, ecode) if (!ecode.inProgress()) { EX_MSG_VERBOSE(ecell.navigationStep, ecode.toString() << " triggers return."); return ecode; }
+#define CHECK_ECODE_SUCCESS(ecell, ecode) if (ecode.isSuccess()) { EX_MSG_VERBOSE(ecell.navigationStep, ecode.toString() << " stops extrapolation sequence."); return ecode; }
+#endif
+
diff --git a/Tracking/TrkExtrapolation/TrkExEngine/TrkExEngine/MaterialEffectsEngine.h b/Tracking/TrkExtrapolation/TrkExEngine/TrkExEngine/MaterialEffectsEngine.h
new file mode 100644
index 0000000000000000000000000000000000000000..11c2e70402f3fae2455112c482dc49051369bb7e
--- /dev/null
+++ b/Tracking/TrkExtrapolation/TrkExEngine/TrkExEngine/MaterialEffectsEngine.h
@@ -0,0 +1,80 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// MaterialEffectsEngine.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef TRKEXINTERFACES_MATERIAKEFFECTSENGINE_H
+#define TRKEXINTERFACES_MATERIAKEFFECTSENGINE_H
+
+// Gaudi
+#include "AthenaBaseComps/AthAlgTool.h"
+// Trk
+#include "TrkExInterfaces/IMaterialEffectsEngine.h"
+#include "TrkExEngine/ExtrapolationMacros.h"
+#include "TrkExUtils/ExtrapolationCell.h"
+#include "TrkExUtils/MaterialInteraction.h"
+#include "TrkExUtils/MaterialUpdateMode.h"
+#include "TrkEventPrimitives/PropDirection.h"
+#include "TrkParameters/TrackParameters.h"
+#include "TrkNeutralParameters/NeutralParameters.h"
+ 
+namespace Trk {
+  
+  class Layer;
+    
+  /** @class MaterialEffectsEngine 
+  
+      Material effects engine interface for charged and neutral (fast track simulation) ,
+      the update is alwyas on the:
+       - eCell.leadParmaeters && eCell.leadLayer 
+       - if eCell.leadPameters == eCell.startParamters clone to new parameters
+         else : update the new parameters
+  
+      @author Andreas Salzburger -at - cern.ch 
+  */
+  class MaterialEffectsEngine : public AthAlgTool, virtual public IMaterialEffectsEngine {
+    public:
+
+      /** Constructor */
+      MaterialEffectsEngine(const std::string&,const std::string&,const IInterface*);
+      
+      /** Destructor */
+      ~MaterialEffectsEngine();
+
+      /** AlgTool initialize method */
+      StatusCode initialize();
+      
+      /** AlgTool finalize method */
+      StatusCode finalize();
+      
+      /** charged extrapolation */
+      virtual ExtrapolationCode handleMaterial(ExCellCharged& ecCharged,
+                                               PropDirection dir=alongMomentum,
+                                               MaterialUpdateStage matupstage=fullUpdate) const;
+
+      /** neutral extrapolation - only for Fatras, dummy implementation here */
+      virtual ExtrapolationCode handleMaterial(ExCellNeutral&,
+                                               PropDirection,
+                                               MaterialUpdateStage) const {return Trk::ExtrapolationCode::InProgress; }
+      
+    protected:
+      /** charged extrapolation */
+      const TrackParameters* updateTrackParameters(const Trk::TrackParameters& parameters,
+                                                   Trk::ExCellCharged& eCell,
+                                                   Trk::PropDirection dir,
+                                                   Trk::MaterialUpdateStage matupstage) const; 
+        
+      MaterialInteraction                          m_interactionFormulae;     //!< the formulas concentrated
+      ParticleMasses                               m_particleMasses;          //!< struct of Particle masses   
+        
+
+  };
+      
+
+} // end of namespace
+
+#endif // TRKEXINTERFACES_MATERIAKEFFECTSENGINE_H
+
diff --git a/Tracking/TrkExtrapolation/TrkExEngine/TrkExEngine/PropagationEngine.h b/Tracking/TrkExtrapolation/TrkExEngine/TrkExEngine/PropagationEngine.h
new file mode 100644
index 0000000000000000000000000000000000000000..73fe210878dba10d75ede5bc3da0ea1a4af9cc71
--- /dev/null
+++ b/Tracking/TrkExtrapolation/TrkExEngine/TrkExEngine/PropagationEngine.h
@@ -0,0 +1,80 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// PropagationEngine.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef TRKEXENGINE_PROPAGATIONENGINE_H
+#define TRKEXENGINE_PROPAGATIONENGINE_H
+
+// Gaudi
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/ToolHandle.h"
+// Trk
+#include "TrkExInterfaces/IPropagationEngine.h"
+#include "TrkExEngine/ExtrapolationMacros.h"
+#include "TrkExUtils/ExtrapolationCell.h"
+#include "TrkEventPrimitives/PropDirection.h"
+#include "TrkParameters/TrackParameters.h"
+#include "TrkNeutralParameters/NeutralParameters.h"
+ 
+namespace Trk {
+  
+  class Surface;
+  class IPropagator;
+    
+  /** @class PropagationEngine 
+  
+      Wrapper around the IPropagator interface,
+      the neutral propagation is solved by using the surface::straightLineIntersection
+      mehtod.
+  
+      @author Andreas Salzburger -at - cern.ch 
+  */
+  class PropagationEngine : public AthAlgTool, virtual public IPropagationEngine {
+    public:
+
+      /** Constructor */
+      PropagationEngine(const std::string&,const std::string&,const IInterface*);
+      
+      /** Destructor */
+      ~PropagationEngine();
+
+      /** AlgTool initialize method */
+      StatusCode initialize();
+      
+      /** AlgTool finalize method */
+      StatusCode finalize();
+
+      /** Avoid shaddowing */
+      using IPropagationEngine::propagate;
+
+      /** resolve the boundary situation - for charged particles */
+      virtual ExtrapolationCode propagate(ExCellCharged& ecCell,
+                                          const Surface& sf,
+                                          PropDirection dir=alongMomentum,
+                                          BoundaryCheck bcheck = true,
+                                          bool returnCurvilinear = true) const;                                                                                         
+
+      /** resolve the boundary situation - for neutral particles */
+      virtual ExtrapolationCode propagate(ExCellNeutral& enCell,
+                                          const Surface& sf,
+                                          PropDirection dir=alongMomentum,
+                                          BoundaryCheck bcheck = true,
+                                          bool returnCurvilinear = true) const;
+       
+    protected:
+        
+      ToolHandle<IPropagator>             m_propagator;
+      double                              m_pathLimitTolerance;
+
+
+  };
+      
+
+} // end of namespace
+
+#endif // TRKEXINTERFACES_INAVIGATIONENGINE_H
+
diff --git a/Tracking/TrkExtrapolation/TrkExEngine/TrkExEngine/StaticEngine.h b/Tracking/TrkExtrapolation/TrkExEngine/TrkExEngine/StaticEngine.h
new file mode 100644
index 0000000000000000000000000000000000000000..bc81f5102f4b3060fe0e630f755f3f6074820315
--- /dev/null
+++ b/Tracking/TrkExtrapolation/TrkExEngine/TrkExEngine/StaticEngine.h
@@ -0,0 +1,144 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// StaticEngine.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef TRKEXENINGE_STATICENGINE_H
+#define TRKEXENINGE_STATICENGINE_H
+
+#ifndef TRKEXENINGE_OUTPUTHELPER 
+#define TRKEXENINGE_OUTPUTHELPER 
+#define OH_CHECKFOUND(object) ( object ? "found" : "not found")
+#endif
+
+// Gaudi
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/ToolHandle.h"
+// Trk
+#include "TrkExInterfaces/IExtrapolationEngine.h"
+#include "TrkExUtils/ExtrapolationCell.h"
+#include "TrkExEngine/ExtrapolationMacros.h"
+#include "TrkParameters/TrackParameters.h"
+#include "TrkNeutralParameters/NeutralParameters.h"
+
+namespace Trk {
+
+  class IPropagationEngine;    
+  class IMaterialEffectsEngine;
+  class INavigationEngine;    
+
+    
+  /** @class StaticEngine
+    
+    Extrapolation engine for static layer & volume setup.
+    
+    This engine relies on the fact that every position in a static layer setup can be uniquely associated to a layer (NavigationLayer or real physical layer),
+    and thus to a voume at navigation level. The extrapolation process within a fully static setup is then realised as a step from layer to layer within a volume,
+    and from volume to volume at a higher level.
+
+    The entire code is written as a template in either charged or neutral parameters.  
+    
+    @author Andreas.Salzburger -at- cern.ch
+  
+  */
+  class StaticEngine : public AthAlgTool, virtual public IExtrapolationEngine {
+
+      public:
+          
+        /** @enum ResolveLayerType 
+            - use for code readability
+        */
+        enum ResolveLayerType {
+          StartLayer                = 0,
+          NavigationLayer           = 1,
+          PassThroughLayer          = 2,
+          SubStructureLayer         = 3,
+          DestinationLayer          = 4,
+          StartAndDestinationLayer  = 6,
+          UndefinedLayer            = 5
+        };          
+        
+        /** Constructor */
+        StaticEngine(const std::string&,const std::string&,const IInterface*);
+        
+        /** Destructor */
+        ~StaticEngine();
+
+        /** AlgTool initialize method */
+        StatusCode initialize();
+        
+        /** AlgTool finalize method */
+        StatusCode finalize();
+        
+        using IExtrapolationEngine::extrapolate;
+        
+        /** charged extrapolation - public interface */
+        virtual ExtrapolationCode extrapolate(ExCellCharged& ecCharged,
+                                              const Surface* sf = 0,
+                                              PropDirection dir=alongMomentum,
+                                              BoundaryCheck bcheck = true) const;
+
+
+        /** neutral extrapolation - public interface */
+        virtual ExtrapolationCode extrapolate(ExCellNeutral& ecNeutral,
+                                              const Surface* sf = 0,
+                                              PropDirection dir=alongMomentum,
+                                              BoundaryCheck bcheck = true) const;
+                         
+        /** define for which GeometrySignature this extrapolator is valid - this is GLOBAL */
+        GeometryType geometryType() const;                             
+                         
+     private:
+        /** main loop extrapolation method */
+        template <class T> ExtrapolationCode extrapolateT(ExtrapolationCell<T>& eCell,
+                                                          const Surface* sf = 0,
+                                                          PropDirection dir=alongMomentum,
+                                                          BoundaryCheck bcheck = true) const;
+                                                                  
+        /** init Navigation for static setup */
+        template <class T> ExtrapolationCode initNavigationT(ExtrapolationCell<T>& eCell,
+                                                             const Surface* sf = 0,
+                                                             PropDirection dir=alongMomentum,
+                                                             BoundaryCheck bcheck = true) const;
+                                                          
+        /** main static layer handling */                                                  
+        template <class T> ExtrapolationCode handleLayerT(ExtrapolationCell<T>& eCell,
+                                                          const Surface* sf = 0,
+                                                          PropDirection dir=alongMomentum,
+                                                          BoundaryCheck bcheck = true) const;  
+
+        /** main sub structure layer handling */                                                  
+        template <class T> ExtrapolationCode resolveLayerT(ExtrapolationCell<T>& eCell,
+                                                           const Trk::Surface* sf,
+                                                           PropDirection dir=alongMomentum,
+                                                           BoundaryCheck bcheck = true,
+                                                           bool hasSubStructure = false,
+                                                           bool isStartLayer = false,
+                                                           bool isDestinationLayer =false) const;  
+        /** handle the failure - as configured */
+        template <class T> ExtrapolationCode handleReturnT(ExtrapolationCode eCode,
+                                                           ExtrapolationCell<T>& eCell,
+                                                           const Surface* sf = 0,
+                                                           PropDirection dir=alongMomentum,
+                                                           BoundaryCheck bcheck = true) const;
+                                                           
+        ToolHandle<IPropagationEngine>                     m_propagationEngine;        //!< the used propagation engine
+        ToolHandle<INavigationEngine>                      m_navigationEngine;         //!< the navigation engine to resolve the boundary
+        ToolHandle<IMaterialEffectsEngine>                 m_materialEffectsEngine;    //!< the material effects updated
+            
+    };
+
+  inline GeometryType StaticEngine::geometryType() const 
+      { return Trk::Static; }
+
+
+} // end of namespace
+
+//!< define the templated function    
+#include "StaticEngine.icc"  
+
+#endif // TRKEXINTERFACES_IStaticEngine_H
+
diff --git a/Tracking/TrkExtrapolation/TrkExEngine/TrkExEngine/StaticEngine.icc b/Tracking/TrkExtrapolation/TrkExEngine/TrkExEngine/StaticEngine.icc
new file mode 100644
index 0000000000000000000000000000000000000000..f41651fbac1f9a3a9cc471606ad545f7af2aea34
--- /dev/null
+++ b/Tracking/TrkExtrapolation/TrkExEngine/TrkExEngine/StaticEngine.icc
@@ -0,0 +1,385 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// StaticEngine.icc, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#include "TrkExInterfaces/INavigationEngine.h"
+#include "TrkExInterfaces/IPropagationEngine.h"
+#include "TrkExInterfaces/IMaterialEffectsEngine.h"
+#include "TrkSurfaces/Surface.h"
+#include "TrkGeometry/TrackingGeometry.h"
+#include "TrkGeometry/TrackingVolume.h"
+#include "TrkGeometry/Layer.h"
+#include <iostream>
+#include <iomanip>
+
+template <class T> Trk::ExtrapolationCode Trk::StaticEngine::extrapolateT(Trk::ExtrapolationCell<T>& eCell,
+                                                                          const Trk::Surface* sf,
+                                                                          Trk::PropDirection pDir,
+                                                                          Trk::BoundaryCheck bcheck) const
+{
+                                                              
+    Trk::ExtrapolationCode eCode = Trk::ExtrapolationCode::InProgress;
+    // ---- [0] check the direct propagation exit
+    // 
+    //  obviously need a surface to exercise the fallback & need to be configured to do so
+    if (sf && eCell.checkConfigurationMode(Trk::ExtrapolationMode::Direct)){
+        EX_MSG_DEBUG(++eCell.navigationStep, "direct extapolation in volume " << eCell.leadVolume->volumeName()); 
+        // propagate to the surface, possible return codes are : SuccessPathLimit, SucessDestination, FailureDestination
+        eCode = m_propagationEngine->propagate(eCell,*sf,pDir,bcheck,eCell.destinationCurvilinear);
+        // eCode can be directly returned
+        return eCode;
+    }
+    EX_MSG_DEBUG(++eCell.navigationStep, "extrapolation in static environment in volume " << eCell.leadVolume->volumeName()); 
+    // evoke or finish the navigation initialization, possible return codes are: 
+    // - InProgress        : everything is fine, extrapolation in static volume is in progress 
+    // - FailureNavigation : navigation setup could not be resolved, but reovery was not configured
+    // - Recovered         : navigation setup could not be resolved, recovery by fallback to directly kicked in (and worked)
+    eCode = initNavigationT<T>(eCell,sf,pDir,bcheck);
+    CHECK_ECODE_CONTINUE(eCell, eCode);
+    // ----- [1] handle the ( leadLayer == endLayer )case :
+    //
+    // - this case does not need a layer to layer loop
+    if (sf && eCell.leadLayer == eCell.endLayer && eCell.initialVolume()){
+        // screen output for startLayer == endLayer 
+        EX_MSG_VERBOSE(eCell.navigationStep, "start and destination layer are identical -> jumping to final propagation."); 
+        // set the leadLayerSurface to the parameters surface
+        eCell.leadLayerSurface = &(eCell.leadParameters->associatedSurface()); 
+        // resolve the layer, it is the final extrapolation 
+        // - InProgress           : layer resolving went without problem
+        // - SuccessPathLimit     : path limit reached & configured to stop (rather unlikely within a layer)
+        // - SuccessMaterialLimit : material limit reached & configured to stop there
+        // if the lead layer is also the startLayer found by initialization -> no material handling
+        eCode =  resolveLayerT<T>(eCell,
+                                  sf,
+                                  pDir,
+                                  bcheck,
+                                  eCell.leadLayer->hasSubStructure(eCell.checkConfigurationMode(Trk::ExtrapolationMode::CollectSensitive)),
+                                  (eCell.leadLayer == eCell.startLayer && eCell.leadVolume == eCell.startVolume),
+                                  true);
+         // Success triggers a return
+         CHECK_ECODE_SUCCESS(eCell, eCode);
+         // extrapolation to destination was not successful
+         // - handle the return as configured (e.g. fallback)                                           
+         return handleReturnT<T>(eCode, eCell, sf, pDir, bcheck);        
+    }   
+    // ----- [2] now do the layer-to-layer loop 
+    //
+    // the volume returns the layers ordered by distance :
+    // -  give potential start and end layer (latter only for the final volume)
+    // - start and end layer will be part of the loop
+    const Trk::Layer* fLayer = eCell.finalVolumeReached() ? eCell.endLayer  : 0;   
+    auto layerIntersections = eCell.leadVolume->materialLayersOrdered(eCell.leadLayer, fLayer,
+                                                                      *eCell.leadParameters,
+                                                                      pDir,
+                                                                      true,
+                                                                      eCell.checkConfigurationMode(Trk::ExtrapolationMode::CollectSensitive));
+    EX_MSG_VERBOSE(eCell.navigationStep, "found a total of " << layerIntersections.size() << " layers for the layer-to-layer loop.");
+    // layer-to-layer loop starts here 
+    for (auto& layerCandidate : layerIntersections ) {
+         // assign the leadLayer 
+         eCell.leadLayer        = layerCandidate.object;
+         // screen output for layer-to-layer loop
+         EX_MSG_VERBOSE(eCell.navigationStep, "layer-to-layer loop - processing layer with index : " << eCell.leadLayer->layerIndex().value());
+         // assign also the leadLayer surface
+         // -  it is the approaching surface for all layers but the very first one (where it's the parameter surface)
+         eCell.leadLayerSurface = (eCell.leadLayer == eCell.startLayer) ? &(eCell.leadParameters->associatedSurface()) : layerCandidate.representation; 
+         // handle the layer, possible returns are :
+         // - InProgress               : fine, whatever happened on the lead layer, may also be missed 
+         // - SuccessWithPathLimit     : propagation towards layer exceeded path limit
+         // - SuccessWithMaterialLimit : material interaction killed track
+         // - FailureDestination       : destination was not hit appropriately
+         eCode = handleLayerT<T>(eCell, sf, pDir, bcheck);
+         EX_MSG_VERBOSE(eCell.navigationStep, "handleLayerT returned extrapolation code " << eCode.toString());
+         // Possibilities are:
+         // - SuccessX  -> return (via handleReturnT)
+         // - FailureX  -> return (via handleReturnT that might evoke a fallback)
+         // - InProgess -> continue layer-to-layer loop
+         if (!eCode.inProgress()) return handleReturnT<T>(eCode, eCell, sf, pDir, bcheck);
+    }   
+    // the layer 2 layer loop is done, the lead parameters are at the last valid option
+    // ----- [3] now resolve the boundary situation, call includes information wheather one is alreay at a boundary
+    //
+    // the navigaiton engine ca trigger different return codes
+    // - InProgress                   : fine, boundary surface has been found
+    // - SuccessWithPathLimit         : propagation towards boundary surface exceeded path limit
+    // - FailureLoop/Navigation       : problem in boundary resolving  
+    eCode = m_navigationEngine->resolveBoundary(eCell, pDir);
+    // SuccessX and FailureX trigger a return
+    CHECK_ECODE_SUCCESS(eCell, eCode);
+    // handle the return of the boudnary resolving                                                          
+    return handleReturnT<T>(eCode, eCell, sf, pDir, bcheck);                                                                                                                 
+}
+
+template <class T> Trk::ExtrapolationCode Trk::StaticEngine::initNavigationT(Trk::ExtrapolationCell<T>& eCell,
+                                                                             const Trk::Surface* sf,
+                                                                             Trk::PropDirection pDir,
+                                                                             Trk::BoundaryCheck bcheck) const 
+{
+    // initialize the Navigation stream ----------------------------------------------------------------------------------------
+    //
+    // this is the global initialization, it only associated direct objects
+    // detailed navigation search needs to be done by the sub engines (since they know best)
+    EX_MSG_DEBUG(++eCell.navigationStep, "complete navigation initialization for static environment.");    
+    // [1] the initial volume 
+    if (eCell.startVolume == eCell.leadVolume && eCell.startLayer) {
+        // - found the initial start layer through association
+        EX_MSG_VERBOSE(eCell.navigationStep, "initial volume, everything set up already.");
+        // assigning it to the leadLayer
+        eCell.leadLayer = eCell.startLayer;
+        // return progress
+        return Trk::ExtrapolationCode::InProgress;
+    }     
+    // [2] any volume if we don't have a leadLayer
+    if (!eCell.leadLayer){
+        // - finding it through global search, never a boundary layer ... convention says that you update by exit
+        eCell.leadLayer = eCell.leadVolume->associatedLayer(eCell.leadParameters->position());
+        EX_MSG_VERBOSE(eCell.navigationStep, "no start layer found yet, looking for it ..." << OH_CHECKFOUND(eCell.leadLayer) );
+    } 
+    // [3] the final volume - everything's fine 
+    if (eCell.leadVolume == eCell.endVolume && sf) {
+        if (eCell.endLayer) {
+          // the end layer had been found already by association
+          EX_MSG_VERBOSE(eCell.navigationStep, "final volume, everything set up already.");
+          return Trk::ExtrapolationCode::InProgress;
+        } else {
+            // make a straight line intersection
+            Trk::Intersection sfI = sf->straightLineIntersection(eCell.leadParameters->position(), pDir*eCell.leadParameters->momentum(), true);
+            // use this to find endVolume and endLayer
+            eCell.endLayer  = eCell.leadVolume->associatedLayer(sfI.position);
+            // if you have a surface you need to require an end layer for the validation, otherwise you need to do a fallbac
+            return eCell.endLayer ? Trk::ExtrapolationCode::InProgress : handleReturnT<T>(Trk::ExtrapolationCode::FailureNavigation, eCell, sf, pDir, bcheck);
+        }
+    } 
+    // return that you're in progress
+    return Trk::ExtrapolationCode::InProgress;     
+}
+
+/** handle the layer  */
+template <class T> Trk::ExtrapolationCode Trk::StaticEngine::handleLayerT(Trk::ExtrapolationCell<T>& eCell,
+                                                                          const Trk::Surface* sf,
+                                                                          Trk::PropDirection pDir,
+                                                                          Trk::BoundaryCheck bcheck) const 
+{   
+    Trk::ExtrapolationCode eCode = Trk::ExtrapolationCode::InProgress;
+    EX_MSG_DEBUG(++eCell.navigationStep, "handle a new layer with layer index " << eCell.leadLayer->layerIndex().value()); 
+    // layer has sub structure - this can be (and the layer will tell you):  
+    //      - sensitive surface which should be tried to hit
+    //      - material sub structure to be resolved (independent of sensitive surface)
+    bool hasSubStructure = eCell.leadLayer->hasSubStructure(eCell.checkConfigurationMode(Trk::ExtrapolationMode::CollectSensitive));
+    // [A] layer is a pure navigation layer and has no sub structure -> skip it, but only if it is not the final layer
+    if (!hasSubStructure && !eCell.leadLayer->layerIndex().value() && eCell.leadLayer != eCell.endLayer){
+        EX_MSG_VERBOSE(eCell.navigationStep, "this layer is a navigation layer -> skipping it ...");   
+        return Trk::ExtrapolationCode::InProgress;
+    }
+    // [B] layer resolving is necessary -> resolve it 
+    // - (a) layer has sub structure - this can be (and the layer will tell you):  
+    //      - sensitive surface which should be tried to hit
+    //      - material sub structure to be resolved (independent of sensitive surface)
+    // - (b) layer is start layer (can not be if there was a volume switch)
+        bool isStartLayer       = eCell.initialVolume() && eCell.leadLayer->onLayer(*eCell.leadParameters); 
+    // - (c) layer is destination layer 
+    //      - final propagation to the layer and update if necessary
+    bool isDestinationLayer = (sf && eCell.leadLayer == eCell.endLayer);
+    //      - postUpdate if necessary
+    if (hasSubStructure || isStartLayer || isDestinationLayer ){
+        // screen output for sub strucutred layer
+        EX_MSG_VERBOSE(eCell.navigationStep, "this layer has sub structure, is start layer, or destination layer -> resolving it ..." );
+        // resolve the layer, it handles all possible return types and gives them directly to extrapolateT<T>
+        // - InProgress           : layer resolving went without problem
+        // - SuccessPathLimit     : path limit reached & configured to stop 
+        // - SuccessMaterialLimit : material limit reached & configured to stop there
+        return resolveLayerT<T>(eCell,sf,pDir,bcheck,hasSubStructure,isStartLayer,isDestinationLayer);
+    }
+    // [C] layer is a material layer without sub structure but material -> pass through
+    // no resolving ob sub structure to be done, an intermediate layer to be crossed
+    EX_MSG_VERBOSE(eCell.navigationStep, "this layer is an intermediate layer without sub structure ->  passing through ...");   
+    //    propagate to it, possible return codes ( with the default of finalPropagation = false):
+    //    - SuccessPathLimit       : propagation to layer exceeded path limit
+    //    - InProgress             : layer was hit successfuly, try to handle the material and sub structure, these are new parameters
+    //    - Recovered              : layer was not hit, so can be ignored in the layer to layer loop 
+    eCode = m_propagationEngine->propagate(eCell,*eCell.leadLayerSurface,pDir,true,eCell.navigationCurvilinear);
+    // check if success was triggered through path limit reached on the way to the layer
+    CHECK_ECODE_SUCCESS(eCell, eCode);
+    // check if the layer was actually hit
+    if (eCode.inProgress()){
+        // successful layer hit 
+        EX_MSG_VERBOSE(eCell.navigationStep, "the layer has been succesful hit ");
+        // layer has no sub-structure : it is an intermediate layer that just needs pass-throgh
+        // return possbilities:
+        // - InProgress            : material update performed or not (depending on material)
+        // - SuccessMaterialLimit  : material limit reached & configured to stop there
+        eCode = m_materialEffectsEngine->handleMaterial(eCell,pDir,Trk::fullUpdate);
+        // check if success was triggered through material limit reached when updating
+        CHECK_ECODE_CONTINUE(eCell, eCode);
+        // record the passive parameters
+        eCell.stepParameters(eCell.leadParameters, Trk::ExtrapolationMode::CollectPassive);
+        // return the progress eCode back to the extrapolateT
+        return eCode;
+    }    
+    // hit or not hit ... it's always in progress since we are in the layer to layer loop
+    return Trk::ExtrapolationCode::InProgress;                                                                             
+}  
+
+
+/** main sub structure layer handling */                                                  
+template <class T> Trk::ExtrapolationCode Trk::StaticEngine::resolveLayerT(Trk::ExtrapolationCell<T>& eCell,
+                                                                           const Trk::Surface* sf,
+                                                                           Trk::PropDirection pDir,
+                                                                           Trk::BoundaryCheck bcheck,
+                                                                           bool hasSubStructure,
+                                                                           bool isStartLayer,
+                                                                           bool isDestinationLayer) const 
+{
+    Trk::ExtrapolationCode eCode = Trk::ExtrapolationCode::InProgress;
+    EX_MSG_DEBUG(++eCell.navigationStep, "resolve layer with" << (hasSubStructure ? " " : "out ") << "sub structure" 
+       <<  (isDestinationLayer ? " -> destination layer." : "") ); 
+
+    // cache the leadLayer - needed for the layer-to-layer loop not to be broken
+    const Trk::Layer* initialLayer = eCell.leadLayer;
+        
+    // [A] the sub structure of the layer needs to be resolved:
+    // - either for sensitive parameters
+    // - or for material substructure
+    if (hasSubStructure){
+        // if the layer is not the start layer - let us propagate to it
+        // - the surfaceOnApproach() call should have sorted out that this is actually an approaching representation
+        if (!isStartLayer){
+           EX_MSG_VERBOSE(eCell.navigationStep, "this is not the start layer, propagate to it."); 
+           // propagate to the representing surface of this layer
+           // - InProgress       : propagation to approaching surface worked - check material update
+           // - SuccessPathLimit : propagation to approaching surface reached the path limit
+           // - Recovered        : layer was not hit, so can be ignored in the layer to layer loop 
+           eCode =  m_propagationEngine->propagate(eCell,*eCell.leadLayerSurface,pDir,true,eCell.sensitiveCurvilinear);  
+           CHECK_ECODE_SUCCESS(eCell,eCode);
+           // the extrapolation to the initial layer did not succeed - skip this layer in the layer-to-layer loop 
+           if (eCode == Trk::ExtrapolationCode::Recovered) return Trk::ExtrapolationCode::InProgress;
+           // fill the corresponding parameters, the material effects updator can attach material to them
+           eCell.stepParameters(eCell.leadParameters, Trk::ExtrapolationMode::CollectPassive);
+           // the correct material layer needs to be assigned
+           if (eCell.leadLayerSurface->materialLayer()){
+               eCell.leadLayer = eCell.leadLayerSurface->materialLayer(); 
+               // now handle the material, return codes are:
+               // - SuccessMaterialLimit : material limit reached, return back
+               // - InProgress           : material update done or not (depending on the material description)
+               eCode = m_materialEffectsEngine->handleMaterial(eCell,pDir,Trk::fullUpdate);
+               CHECK_ECODE_CONTINUE(eCell, eCode);
+           }
+        } // @TODO check postUpdate for start surface in sub structure environment
+        // resolve the substructure - the surfaces given by the layer, needs to be searched for with anyDirection 
+        std::vector<Trk::SurfaceIntersection> cSurfaces;
+        // this will give you the compatible up to the endSurface (without the endSurface (sf) if given)
+        // - leadParameters->associatedSurface() are included or not, depending if it is the startLayer or not 
+        size_t ncSurfaces = eCell.leadLayer->compatibleSurfaces(cSurfaces,
+                                                                *eCell.leadParameters,
+                                                                pDir,
+                                                                bcheck,
+                                                                (!isStartLayer ? eCell.leadLayerSurface : 0),
+                                                                (isDestinationLayer ? sf : 0) );
+        
+        EX_MSG_VERBOSE(eCell.navigationStep, "found " <<  ncSurfaces << " candidate sensitive surfaces to test."); 
+        // check if you have to do something
+        if (ncSurfaces){
+            // now loop over the surfaces:
+            // the surfaces will be sorted @TODO integrate pathLength propagation into this
+            for (auto& csf : cSurfaces ) {
+                EX_MSG_VERBOSE(eCell.navigationStep, "trying candidate surfaces with straight line path length " << csf.intersection.pathLength); 
+                // propagate to the compatible surface, return types are (pathLimit failure is excluded by Trk::anyDirection for the moment):
+                // - InProgress : propagation to compatible surface worked
+                // - Recovered  : propagation to compatible surface did not work, leadParameters stay the same
+                // eCode =  m_propagationEngine->propagate(eCell,*(csf.object),pDir,true,eCell.sensitiveCurvilinear);
+                eCode =  m_propagationEngine->propagate(eCell,*(csf.object),pDir,true,eCell.sensitiveCurvilinear);
+                
+                // check if the propagation was successful 
+                if (eCode.inProgress()){
+                    EX_MSG_VERBOSE(eCell.navigationStep, "successfully hit sub structure surface."); 
+                    // record the parameters as sensitive or passive depending on the surface
+                    Trk::ExtrapolationMode::eMode emode =  csf.object->isActive() ? Trk::ExtrapolationMode::CollectSensitive : Trk::ExtrapolationMode::CollectPassive;
+                    // fill the corresponding parameters, the material effects updator can attach material to them
+                    eCell.stepParameters(eCell.leadParameters, emode);
+                    // check if the surface holds a material layer 
+                    // - yes  : it is a sub surface that has a material layer attached
+                    // - no 1 : it is a sub surface and has no material attached
+                    // - no 2 : it is the representing layer for the material integration (this case can be caught by surface pointer comparison)
+                    if (csf.object->materialLayer() || ( csf.object->associatedLayer() && csf.object == &(csf.object->associatedLayer()->surfaceRepresentation()) ) ) {
+                        // the resolved surface has material, set the leadLayer to 
+                        // - the materialLayer ( has higher priority than the associatedLayer() )
+                        // - the associatedLayer ( it is the representing layer )
+                        eCell.leadLayer      = csf.object->materialLayer() ? csf.object->materialLayer() : csf.object->associatedLayer();
+                        // now handle the material, return codes are:
+                        // - SuccessMaterialLimit : material limit reached,return back
+                        // - InProgress           : material update done or not (depending on the material description)
+                        eCode = m_materialEffectsEngine->handleMaterial(eCell,pDir,Trk::fullUpdate);
+                        CHECK_ECODE_CONTINUE(eCell, eCode);
+                    }
+                } 
+           } // loop over test surfaces done
+        } // there are compatible surfaces          
+    } 
+    
+    // the layer is a destination layer
+    // - the final propagation call is indepenent of whether sub structure was resolved or not
+    // - the eCell.leadParameters are at the last possible parameters
+    if (sf && isDestinationLayer) {
+        // [B] the layer is start and destination layer but has no sub-structure 
+        // -> propagation to destination surface
+        //  (a) the starting layer is the same layer :
+        // - neither preUpdate nore postUpdate to be done, this is old-style within-layer extrapolation 
+        // - material will be taken into account either when the layer was reached from another layer 
+        //   or when the layer is left to another destination
+        //  (b) the starting layer is not the same layer :
+        // - apply the preUpdate on the parameters whein they reached the surface    
+        // Possible return types:
+        // - SuccessDestion      : great, desintation surface hit
+        // - SuccessPathLimit    : pathlimit was reached on the way to the destination surface 
+        eCode = m_propagationEngine->propagate(eCell,*sf,pDir,bcheck,eCell.destinationCurvilinear);
+        EX_MSG_VERBOSE(eCell.navigationStep, "attempt to hit destination surface resulted in " << eCode.toString() ); 
+        // preUpdate needed when the layer is NOT the startLayer - or if sub structure resolving happened
+        if ( (!isStartLayer || hasSubStructure) &&  (eCode != Trk::ExtrapolationCode::SuccessPathLimit) ){ 
+            // the resolved surface has material, set the leadLayer to 
+            // - the materialLayer ( has higher priority than the associatedLayer() )
+            // - the associatedLayer ( if no materialLayer is not there )
+            eCell.leadLayer      = sf->materialLayer() ? sf->materialLayer() : sf->associatedLayer();
+            // finally do the material update 
+            // - this is the final call, no need to check for SuccessMaterialLimit
+            // - however only do the preUpdate if the destination was successfully hit (and no path limit kicked in)
+            // the material effects updator usually returns inProgress, this needs to be ingored
+            m_materialEffectsEngine->handleMaterial(eCell,pDir,Trk::preUpdate);
+        }   
+        // return what you have handleLayerT or extrapolateT will resolve that
+        return eCode;        
+    }
+    // reset the lead layer to ensure the layer-to-layer loop 
+    eCell.leadLayer = initialLayer;
+    // return the code:
+    // - if it came until here, return InProgress to not break the layer-to-layer loop
+    return Trk::ExtrapolationCode::InProgress;
+}  
+
+/** handle the failure - as configured */
+template <class T> Trk::ExtrapolationCode Trk::StaticEngine::handleReturnT(Trk::ExtrapolationCode eCode,
+                                                                           Trk::ExtrapolationCell<T>& eCell,
+                                                                           const Trk::Surface* sf,
+                                                                           Trk::PropDirection pDir,
+                                                                           Trk::BoundaryCheck bcheck) const 
+{   
+    EX_MSG_DEBUG(++eCell.navigationStep, "handleReturnT with code " << eCode.toString() << " called." ); 
+    if (eCode.isSuccessOrRecovered() || eCode.inProgress() ){
+        EX_MSG_VERBOSE(eCell.navigationStep, "leaving static extrapolator successfully with code " << eCode.toString()); 
+        return eCode;
+    }
+    EX_MSG_VERBOSE(eCell.navigationStep, "failure detected as " << eCode.toString() << " - checking fallback configuration."); 
+    // obviously we need a surface to exercise the fallback    
+    if (sf && !eCell.checkConfigurationMode(Trk::ExtrapolationMode::AvoidFallback)){
+        EX_MSG_VERBOSE(eCell.navigationStep, "fallback configured. Trying to hit destination surface from last valid parameters."); 
+        // check if you hit the surface, could still be stopped by PathLimit, but would also count as recovered
+        eCode = m_propagationEngine->propagate(eCell,*sf,pDir,bcheck,eCell.destinationCurvilinear);
+    }    
+    // nothing to try anynore
+    return eCode;                                                                                  
+}
+  
+                                                                                                          
diff --git a/Tracking/TrkExtrapolation/TrkExEngine/TrkExEngine/StaticNavigationEngine.h b/Tracking/TrkExtrapolation/TrkExEngine/TrkExEngine/StaticNavigationEngine.h
new file mode 100644
index 0000000000000000000000000000000000000000..ddbf4b3ef1fba9f1d2a8c5e9fdd1d6985db4e41a
--- /dev/null
+++ b/Tracking/TrkExtrapolation/TrkExEngine/TrkExEngine/StaticNavigationEngine.h
@@ -0,0 +1,103 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// StaticNavigationEngine.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef TRKEXENGINE_STATICNAVIGATIONENGINE_H
+#define TRKEXENGINE_STATICNAVIGATIONENGINE_H
+
+// Gaudi
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/ToolHandle.h"
+// Trk
+#include "TrkExInterfaces/INavigationEngine.h"
+#include "TrkExEngine/ExtrapolationMacros.h"
+#include "TrkExUtils/ExtrapolationCell.h"
+#include "TrkParameters/TrackParameters.h"
+#include "TrkNeutralParameters/NeutralParameters.h"
+#include "TrkVolumes/BoundarySurface.h"
+// throw GaudiExceptions where necessary
+#include "GaudiKernel/GaudiException.h"
+
+
+namespace Trk {
+
+  class IPropagationEngine;
+  class IMaterialEffectsEngine;
+  class TrackingGeometry;
+    
+  /** @class StaticNavigationEntine
+    
+      The static navigation engine for finding the next volume,
+      propagate to the boundary, can be shared with other engines that have a static frame.
+    
+      @author Andreas.Salzburger -at- cern.ch
+    */    
+  class StaticNavigationEngine : public AthAlgTool, virtual public INavigationEngine {
+
+      public:
+        /** Constructor */
+        StaticNavigationEngine(const std::string&,const std::string&,const IInterface*);
+        
+        /** Destructor */
+        ~StaticNavigationEngine();
+
+        /** AlgTool initialize method */
+        StatusCode initialize();
+        
+        /** AlgTool finalize method */
+        StatusCode finalize();
+
+        /** avoid method shaddowing */
+        using INavigationEngine::resolveBoundary;
+
+        /** resolve the boundary situation - for charged particles */
+        virtual ExtrapolationCode resolveBoundary(Trk::ExCellCharged& eCell, PropDirection dir=alongMomentum) const;                                                                                         
+
+        /** resolve the boundary situation - for neutral particles */
+        virtual ExtrapolationCode resolveBoundary(Trk::ExCellNeutral& eCelll, PropDirection dir=alongMomentum) const;
+        
+     private:
+        /** resolve the boundary situation */
+        template <class T> ExtrapolationCode resolveBoundaryT(ExtrapolationCell<T>& eCell,
+                                                             PropDirection dir=alongMomentum) const;
+                                                             
+        /** deal with the boundary Surface - called by resolveBoundary */
+        template <class T> ExtrapolationCode handleBoundaryT(ExtrapolationCell<T>& eCell,
+                                                             const BoundarySurface<TrackingVolume>& bSurfaceTV, 
+                                                             PropDirection dir=alongMomentum,
+                                                             bool stepout=false) const;     
+                                             
+
+        //!< retrieve TrackingGeometry
+        StatusCode  updateTrackingGeometry() const; 
+        
+        //!< return and retrieve
+        const TrackingGeometry& trackingGeometry() const throw (GaudiException);
+
+        ToolHandle<IPropagationEngine>                       m_propagationEngine;        //!< the used propagation engine
+        ToolHandle<IMaterialEffectsEngine>                   m_materialEffectsEngine;    //!< the material effects updated
+
+        mutable const TrackingGeometry*                      m_trackingGeometry;          //!< the tracking geometry owned by the navigator
+        std::string                                          m_trackingGeometryName;      //!< Name of the TrackingGeometry as given in Detector Store
+            
+    };
+
+inline const Trk::TrackingGeometry& StaticNavigationEngine::trackingGeometry() const throw (GaudiException) {
+    if (!m_trackingGeometry && updateTrackingGeometry().isFailure()){
+        ATH_MSG_ERROR("Could not load TrackingGeometry with name '" << m_trackingGeometryName << "'. Aborting." );
+        throw GaudiException("StaticNavigationEngine", "Problem with TrackingGeometry loading.", StatusCode::FAILURE);
+    }
+    return (*m_trackingGeometry);
+}
+
+} // end of namespace
+
+//!< define the templated function    
+#include "StaticNavigationEngine.icc"  
+
+#endif // TRKEXENGINE_STATICNAVIGATIONENGINE_H
+
diff --git a/Tracking/TrkExtrapolation/TrkExEngine/TrkExEngine/StaticNavigationEngine.icc b/Tracking/TrkExtrapolation/TrkExEngine/TrkExEngine/StaticNavigationEngine.icc
new file mode 100644
index 0000000000000000000000000000000000000000..0924e1bcb678f77d0dea6d8fcef5d92a4f580c52
--- /dev/null
+++ b/Tracking/TrkExtrapolation/TrkExEngine/TrkExEngine/StaticNavigationEngine.icc
@@ -0,0 +1,184 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// StaticNavigationEngine.icc, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#include "TrkExInterfaces/IPropagationEngine.h"
+#include "TrkExInterfaces/IMaterialEffectsEngine.h"
+#include "TrkGeometry/TrackingVolume.h"
+#include "TrkGeometry/TrackingGeometry.h"
+#include "TrkVolumes/BoundarySurface.h"
+#include "GeoPrimitives/GeoPrimitives.h"
+
+/** handle the failure - as configured */
+template <class T> Trk::ExtrapolationCode Trk::StaticNavigationEngine::resolveBoundaryT(Trk::ExtrapolationCell<T>& eCell,
+                                                                                        Trk::PropDirection pDir) const 
+{   
+    EX_MSG_DEBUG(++eCell.navigationStep, "resolve boundary situation leaving '"<< eCell.leadVolume->volumeName() 
+                << (int(pDir) > 0 ? "' along momentum." : "' opposite momentum.") );
+    // initialize the extrapolation code to progress
+    Trk::ExtrapolationCode eCode = Trk::ExtrapolationCode::InProgress;
+    // [1] ------------------------ fast boundary access : take straight line estimates as navigation guide --------------
+    auto boundaryIntersections = eCell.leadVolume->boundarySurfacesOrdered(*eCell.leadParameters,
+                                                                           pDir,
+                                                                           eCell.onLastBoundary() );
+    EX_MSG_VERBOSE(eCell.navigationStep, "found " << boundaryIntersections.size() << " boundary surfaces to try"
+                   << ( eCell.onLastBoundary() ? " - starting from last boundary." : "." ) );
+    // remember them for the slow acces 
+    std::map< const Trk::BoundarySurface<Trk::TrackingVolume>*, bool > bSurfacesTried;
+    for (auto& boundaryCandidate : boundaryIntersections){
+        // the surface of the 
+        const Trk::BoundarySurface<Trk::TrackingVolume>* bSurfaceTV = boundaryCandidate.object;
+        // skip if it's the last boundary surface
+        if (eCell.onLastBoundary() && &bSurfaceTV->surfaceRepresentation() == eCell.lastBoundarySurface ) continue;
+        // check this boudnary, possible return codes are:
+        // - SuccessPathLimit     : propagation to boundary caused PathLimit to be fail @TODO implement protection againg far of tries
+        // - SuccessMaterialLimit : boundary was reached and material update on boundary reached limit
+        // - InProgress           : boundary was reached and ready for continueing the navigation
+        // - UnSet                : boundary was not reached, try the next one
+        // - FailureLoop          : next Volume was previous Volume
+        eCode = handleBoundaryT<T>(eCell,*bSurfaceTV,pDir);
+        CHECK_ECODE_SUCCESS(eCell, eCode);
+        // Failure or Unset are not triggering a return, try more sophisticated navigation 
+        if (!eCode.inProgress()){
+            EX_MSG_VERBOSE(eCell.navigationStep, "boundary surface not reached with " << eCode.toString() << ", skipping.");
+            // book keeping for the slow access not to try again the same stuff
+            bSurfacesTried[bSurfaceTV] = false;
+            // skip to the next surface if there's one
+            continue;
+        } 
+        EX_MSG_VERBOSE(eCell.navigationStep, "boundary surface handling yielded code " << eCode.toString());
+        // set that this was the last boundary surface
+        eCell.lastBoundarySurface = &bSurfaceTV->surfaceRepresentation();
+        // and return the code yielded by the handleBoundaryT 
+        return eCode;
+    }
+    // [2] ------------------------ slow boundary access : take all boundary surfaces and simply try --------------
+    EX_MSG_VERBOSE(eCell.navigationStep, "fast boundary navigation did not succeeed - trying slow navigation now.");
+    // ignore the ones you have tried already 
+    for (auto& bSurface : eCell.leadVolume->boundarySurfaces() ){
+        // we tried this one already, no point to do it again
+        if ( bSurfacesTried.size() && bSurfacesTried.find(bSurface.getPtr()) != bSurfacesTried.end() ) continue;
+        // skip if it's the last boundary surface
+        if ( &bSurface->surfaceRepresentation() == eCell.lastBoundarySurface ) continue;
+        EX_MSG_VERBOSE(eCell.navigationStep, "trying a boundary surface.");
+        // there is now loop protection in the slow access, needs to be done by hand
+        // check this boudnary, possible return codes are:
+        // - SuccessPathLimit     : propagation to boundary caused PathLimit to be fail @TODO implement protection againg far of tries
+        // - SuccessMaterialLimit : boundary was reached and material update on boundary reached limit
+        // - InProgress           : boundary was reached and ready for continueing the navigation
+        // - UnSet                : boundary was not reached, try the next one
+        eCode = handleBoundaryT<T>(eCell,*bSurface.getPtr(),pDir);
+        CHECK_ECODE_SUCCESS(eCell, eCode);
+        // Failure or Unset are not triggering a return, try more sophisticated navigation 
+        if (!eCode.inProgress()){
+            EX_MSG_VERBOSE(eCell.navigationStep, "boundary surface not reached with " << eCode.toString() << ", skipping.");
+            // skip to the next surface if there's one
+            continue;
+        }
+        EX_MSG_VERBOSE(eCell.navigationStep, "boundary surface handling yielded code " << eCode.toString());
+        // set that this was the last boundary surface
+        eCell.lastBoundarySurface = &bSurface->surfaceRepresentation();
+        // and return the code yielded by the handleBoundaryT 
+        return eCode;
+    }
+    // [3] ------------------------ slowest boundary access : step-out-of-volume approach -------------------------
+    EX_MSG_VERBOSE(eCell.navigationStep, "slow boundary navigation did not succeeed - trying step-out-of-volume approach now");
+    for (auto& boundaryCandidate : boundaryIntersections){
+        // the surface of the 
+        const Trk::BoundarySurface<Trk::TrackingVolume>* bSurfaceTV = boundaryCandidate.object;
+        // check this boudnary, possible return codes are:
+        // - SuccessPathLimit     : propagation to boundary caused PathLimit to be fail @TODO implement protection againg far of tries
+        // - SuccessMaterialLimit : boundary was reached and material update on boundary reached limit
+        // - InProgress           : boundary was reached and ready for continueing the navigation
+        // - UnSet                : boundary was not reached, try the next one
+        // - FailureLoop          : next Volume was previous Volume
+        eCode = handleBoundaryT<T>(eCell,*bSurfaceTV,pDir,true);
+        CHECK_ECODE_SUCCESS(eCell, eCode);
+        // Failure or Unset are not triggering a return, try more sophisticated navigation 
+        if (!eCode.inProgress()){
+            EX_MSG_VERBOSE(eCell.navigationStep, "boundary surface not reached with " << eCode.toString() << ", skipping.");
+            // skip to the next surface if there's one
+            continue;
+        } 
+        EX_MSG_VERBOSE(eCell.navigationStep, "boundary surface handling yielded code " << eCode.toString());
+        // set that this was the last boundary surface
+        eCell.lastBoundarySurface = &bSurfaceTV->surfaceRepresentation();
+        // and return the code yielded by the handleBoundaryT 
+        return eCode;
+    }   
+    // return it back
+    EX_MSG_DEBUG(eCell.navigationStep, "could not resolve the boundary situation. Exiting.");
+    return Trk::ExtrapolationCode::FailureNavigation;                                                                                 
+}  
+
+/** handle the failure - as configured */
+template <class T> Trk::ExtrapolationCode Trk::StaticNavigationEngine::handleBoundaryT(Trk::ExtrapolationCell<T>& eCell,
+                                                                                       const Trk::BoundarySurface<Trk::TrackingVolume>& bSurfaceTV,
+                                                                                       Trk::PropDirection pDir,
+                                                                                       bool stepout) const 
+{
+    // get the bondary surface and compare with last one to prevent loops
+    const Trk::Surface& bSurface = bSurfaceTV.surfaceRepresentation(); 
+    // propagate the parameters to the boundary (force boundaryCheck to true in case it is not a step-out trial), possible return codes :
+    // - SuccessPathLimit : pathLimit reached during propagation
+    // - InProgress       : boundary reached
+    // - Recovered        : boundary not reached
+    Trk::ExtrapolationCode eCode = m_propagationEngine->propagate(eCell,bSurface,pDir,!stepout,eCell.destinationCurvilinear);
+    CHECK_ECODE_SUCCESS(eCell, eCode);
+    // check for progress 
+    if (eCode.inProgress()){         
+        EX_MSG_VERBOSE(eCell.navigationStep, "parameters on boundary surface created, moving to next volume."); 
+        // get the nextVolume - modify the position in case you have a step out trial, take attachment otherwise
+        const Trk::TrackingVolume* nextVolume = stepout ?
+                trackingGeometry().lowestTrackingVolume(Amg::Vector3D(eCell.leadParameters->position()+pDir*eCell.leadParameters->momentum().unit())) :
+                bSurfaceTV.attachedVolume(eCell.leadParameters->position(), eCell.leadParameters->momentum(), pDir);
+        // check if it is a boundary reached case
+        // - geometrySignature change and configuration to stop then triggers a Success 
+        bool stopAtThisBoundary = eCell.checkConfigurationMode(Trk::ExtrapolationMode::StopAtBoundary) 
+                                  && (nextVolume->geometrySignature() != eCell.leadVolume->geometrySignature());        
+        // fill the boundary into the cache if successfully hit boundary surface
+        // - only cache if those are not the final parameters caused by a StopAtBoundary
+        if (!stopAtThisBoundary)
+            eCell.stepParameters(eCell.leadParameters, Trk::ExtrapolationMode::CollectBoundary);
+        // loop protection - relaxed for the cases where you start from the boundary
+        if (eCell.leadVolume == nextVolume ) {
+            // the start parameters where on the boundary already give a relaxed return code
+            if (&bSurface == eCell.lastBoundarySurface) return Trk::ExtrapolationCode::Unset;
+            // give some screen output as of why this happens
+            EX_MSG_VERBOSE(eCell.navigationStep, "loop detected while trying to leave TrackingVolume '" << nextVolume->volumeName() << ".");
+            // return a loop failure, parameter deletion will be done by cache
+            return Trk::ExtrapolationCode::FailureLoop;
+        }
+        // update the with the information of the layer material - will change the leadParameters
+        if (bSurface.materialLayer()) {
+            // assign the new lead layer for material inclusion
+            eCell.leadLayer = bSurface.materialLayer();
+            // now handle the material, possible return codes: 
+            // - InProgress            : material update performed or not (depending on material)
+            // - SuccessMaterialLimit  : material limit reached & configured to stop there
+            eCode = m_materialEffectsEngine->handleMaterial(eCell,pDir,Trk::fullUpdate);
+            CHECK_ECODE_SUCCESS(eCell, eCode);
+        }
+        // break if configured to break at volume boundary and signature change
+        if (stopAtThisBoundary){
+            EX_MSG_VERBOSE(eCell.navigationStep, "geometry signature change from " << eCell.leadVolume->geometrySignature()  << " to " << nextVolume->geometrySignature());
+            // return the boundary reached     
+            return Trk::ExtrapolationCode::SuccessBoundaryReached;
+        } 
+        // remember the last boundary surface for loop protection
+        eCell.lastBoundarySurface             = &bSurface;
+        eCell.lastBoundaryParameters          = eCell.leadParameters;
+        // set next volume and reset lead layer
+        eCell.leadVolume                      = nextVolume;    
+        eCell.leadLayer                       = 0;
+        // we have bParameters -> break the loop over boundaryIntersections
+        return  Trk::ExtrapolationCode::InProgress;
+     }
+
+     // you need to keep on trying 
+     return Trk::ExtrapolationCode::Unset;
+ }
diff --git a/Tracking/TrkExtrapolation/TrkExEngine/cmt/requirements b/Tracking/TrkExtrapolation/TrkExEngine/cmt/requirements
new file mode 100644
index 0000000000000000000000000000000000000000..97ff8ce49994fe8cbe5fbdcd629acc74c0a6a38b
--- /dev/null
+++ b/Tracking/TrkExtrapolation/TrkExEngine/cmt/requirements
@@ -0,0 +1,36 @@
+package TrkExEngine
+
+manager Andreas Salzburger <Andreas.Salzburger@cern.ch>
+author  Andreas Salzburger <Andreas.Salzburger@cern.ch>
+
+#################################################################
+# public use statements
+use AtlasPolicy            AtlasPolicy-*
+use GeoPrimitives          GeoPrimitives-*          DetectorDescription
+use GaudiInterface         GaudiInterface-*         External
+use AthenaBaseComps        AthenaBaseComps-*        Control
+use TrkExInterfaces        TrkExInterfaces-*        Tracking/TrkExtrapolation
+use TrkExUtils             TrkExUtils-*             Tracking/TrkExtrapolation
+use TrkParameters          TrkParameters-*          Tracking/TrkEvent
+use TrkNeutralParameters   TrkNeutralParameters-*   Tracking/TrkEvent
+use TrkEventPrimitives     TrkEventPrimitives-*     Tracking/TrkEvent
+use TrkVolumes             TrkVolumes-*             Tracking/TrkDetDescr
+use TrkSurfaces            TrkSurfaces-*            Tracking/TrkDetDescr
+use TrkGeometry            TrkGeometry-*            Tracking/TrkDetDescr
+use TrkDetDescrInterfaces  TrkDetDescrInterfaces-*  Tracking/TrkDetDescr
+
+
+#################################################################
+# private use statements
+private
+use TrkDetDescrUtils       TrkDetDescrUtils-*       Tracking/TrkDetDescr
+
+public
+library TrkExEngine *.cxx components/*.cxx
+apply_pattern declare_python_modules files="*.py"
+apply_pattern component_library
+
+private
+#macro cppdebugflags '$(cppdebugflags_s)'
+#macro_remove componentshr_linkopts "-Wl,-s"
+macro DOXYGEN_IMAGE_PATH "../doc/images"
\ No newline at end of file
diff --git a/Tracking/TrkExtrapolation/TrkExEngine/doc/mainpage.h b/Tracking/TrkExtrapolation/TrkExEngine/doc/mainpage.h
new file mode 100644
index 0000000000000000000000000000000000000000..d58f97cb9f88e3f6f50f0ee3c891958db425cfc2
--- /dev/null
+++ b/Tracking/TrkExtrapolation/TrkExEngine/doc/mainpage.h
@@ -0,0 +1,57 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/**
+
+ <i>This page has been automatically generated by the tool. Please remove this line when you start creating your own mainpage</i>
+
+@mainpage
+
+New Extrapolation package
+=========================
+
+The TrkExEngine package was created to eventually repace the TrkExTools package by redefining and centralising the interface of all extrapolation operations needed for reconstruction and fast track simulation.
+It has been re-designed in accordance to the updated track parameterisation (TrkParametersBase).
+
+Design concepts and implementation
+==================================
+
+Data Flow
+---------
+
+The major design choice of the new TrkExEngine package is a division into optimised engines for the given geometry setup. 
+The tracking geometry (TrkGeometry) supports the following different geometyr types:
+- static   : a layer based setup that is interlinked and pre-ordered at the tracking geometry building
+- dense    : a dense volume description, especially made for the STEP propagator (TrkExSTEP_Propagator)
+- detached : a mixed setup of freely based volumes, especially made fort the STEP propagator
+
+One single master engine (Trk::ExtrapolationEngine) steers the dataflow and the navigation through the high level tracking volumes,
+calling the optimised sub engine for the different tracking volumes. The type of the tracking volume is provided by the node itself via an enumaration object.
+
+The extrapolation, navigation and eventually needed material or jacobian collection is done using a cache object (Trk::ExtrapolationCell) which is handed over from engine to engine.
+
+
+The ExtrapolationCell
+---------------------
+
+The key object of the extrapolation engine is the Trk::ExtrapolationCell class, which is used to start, configure and steer the extrapolation process.
+This class is a templated object and can be used with charged (TrkParameters) and neutral (TrkNeutralParameters) parameters.
+The ExtrapolationEngine itself thus supports the exact same interface for charged and neutral parameters.
+
+The ExtrapolationCell is the single cache allowed in the new ExtrapolationEngine and --- since it is the input/output object --- turns the master engine into a thread -safe component.
+
+
+The ExtrapolationCode
+---------------------
+
+The main return class of the ExtrapolationEngine package is a ExtrapolationCode class, which carries the current status of the extrapoaltion.
+During the extrapolation process, the code forwarded between the different components is usually Trk::ExtrapolationCode::InProgress,
+while success and failure codes are used to indicate different destination parameters or eventual failures during the extrapolation progress.
+
+
+@htmlinclude used_packages.html
+
+@include requirements
+
+*/
diff --git a/Tracking/TrkExtrapolation/TrkExEngine/python/AtlasExtrapolationEngine.py b/Tracking/TrkExtrapolation/TrkExEngine/python/AtlasExtrapolationEngine.py
new file mode 100644
index 0000000000000000000000000000000000000000..881ec2941d03e6abf10158d40bca99ce339222ad
--- /dev/null
+++ b/Tracking/TrkExtrapolation/TrkExEngine/python/AtlasExtrapolationEngine.py
@@ -0,0 +1,106 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+######################################################
+# AtlasExtrapolationEngine module
+#
+# it inherits from Trk__Extrapolator and uses
+# the AtlasTrackingGeometrySvc
+#
+######################################################
+
+# import the include statement
+from AthenaCommon.Include import Include, IncludeError, include
+
+# import the ExtrapolationEngine configurable
+from TrkExEngine.TrkExEngineConf import Trk__ExtrapolationEngine as ExEngine
+
+# define the class
+class AtlasExtrapolationEngine( ExEngine ):
+    # constructor
+    def __init__(self,name = 'Extrapolation', nameprefix = 'Atlas', ToolOutputLevel = None, TrackingGeometrySvc = None):
+       
+        # get the correct TrackingGeometry setup
+        if not TrackingGeometrySvc :
+            from TrkDetDescrSvc.AtlasTrackingGeometrySvc import AtlasTrackingGeometrySvc
+            from AthenaCommon.AppMgr import ServiceMgr as svcMgr
+            AtlasTrackingGeometrySvc = svcMgr.AtlasTrackingGeometrySvc 
+        else :
+            AtlasTrackingGeometrySvc = TrackingGeometrySvc
+
+        # import the ToolSvc
+        from AthenaCommon.AppMgr import ToolSvc
+        if 'ToolSvc' not in dir() :
+            ToolSvc = ToolSvc()
+
+        # load the RungeKutta Propagator
+        from TrkExRungeKuttaPropagator.TrkExRungeKuttaPropagatorConf import Trk__RungeKuttaPropagator
+        RungeKuttaPropagator = Trk__RungeKuttaPropagator(name = nameprefix+'RungeKuttaPropagator')
+        if ToolOutputLevel :
+            RungeKuttaPropagator.OutputLevel     = ToolOutputLevel
+        ToolSvc += RungeKuttaPropagator
+        
+        # from the Propagator create a Propagation engine to handle path length
+        from TrkExEngine.TrkExEngineConf import Trk__PropagationEngine
+        StaticPropagator = Trk__PropagationEngine(name = nameprefix+'StaticPropagation')
+        # give the tools it needs 
+        StaticPropagator.Propagator               = RungeKuttaPropagator
+        # configure output formatting               
+        StaticPropagator.OutputPrefix             = '[SP] - '
+        StaticPropagator.OutputPostfix            = ' - '
+        if ToolOutputLevel : 
+            StaticPropagator.OutputLevel          = ToolOutputLevel
+        # add to tool service
+        ToolSvc += StaticPropagator
+        
+        # load the material effects engine
+        from TrkExEngine.TrkExEngineConf import Trk__MaterialEffectsEngine
+        MaterialEffectsEngine = Trk__MaterialEffectsEngine(name = nameprefix+'MaterialEffects')
+        # configure output formatting               
+        MaterialEffectsEngine.OutputPrefix        = '[ME] - '
+        MaterialEffectsEngine.OutputPostfix       = ' - '
+        if ToolOutputLevel : 
+            MaterialEffectsEngine.OutputLevel     = ToolOutputLevel
+        # add to tool service
+        ToolSvc += MaterialEffectsEngine
+        
+        # load the static navigation engine
+        from TrkExEngine.TrkExEngineConf import Trk__StaticNavigationEngine
+        StaticNavigator = Trk__StaticNavigationEngine(name = nameprefix+'StaticNavigation')
+        # give the tools it needs 
+        StaticNavigator.PropagationEngine        = StaticPropagator
+        StaticNavigator.MaterialEffectsEngine    = MaterialEffectsEngine
+        # Geometry name
+        StaticNavigator.TrackingGeometry         = AtlasTrackingGeometrySvc.TrackingGeometryName
+        # configure output formatting               
+        StaticNavigator.OutputPrefix             = '[SN] - '
+        StaticNavigator.OutputPostfix            = ' - '
+        if ToolOutputLevel : 
+            StaticNavigator.OutputLevel              = ToolOutputLevel
+        # add to tool service
+        ToolSvc += StaticNavigator
+        
+        
+        # load the Static ExtrapolationEngine
+        from TrkExEngine.TrkExEngineConf import Trk__StaticEngine
+        StaticExtrapolator = Trk__StaticEngine(name = nameprefix+'StaticExtrapolation')
+        # give the tools it needs 
+        StaticExtrapolator.PropagationEngine        = StaticPropagator
+        StaticExtrapolator.MaterialEffectsEngine    = MaterialEffectsEngine
+        StaticExtrapolator.NavigationEngine         = StaticNavigator
+        # configure output formatting               
+        StaticExtrapolator.OutputPrefix             = '[SE] - '
+        StaticExtrapolator.OutputPostfix            = ' - '
+        if ToolOutputLevel : 
+            StaticExtrapolator.OutputLevel              = ToolOutputLevel
+        # add to tool service
+        ToolSvc += StaticExtrapolator
+       
+        # call the base class constructor
+        ExEngine.__init__(self, name=nameprefix+'Extrapolation',\
+                          ExtrapolationEngines   = [ StaticExtrapolator ], \
+                          TrackingGeometrySvc    = AtlasTrackingGeometrySvc, \
+                          OutputPrefix           = '[ME] - ', \
+                          OutputPostfix          = ' - ')
+        # set the output level
+        if ToolOutputLevel :
+            self.OutputLevel = ToolOutputLevel
diff --git a/Tracking/TrkExtrapolation/TrkExEngine/python/__init__.py b/Tracking/TrkExtrapolation/TrkExEngine/python/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..74583d364ec2ca794156596c7254d9b234a940c6
--- /dev/null
+++ b/Tracking/TrkExtrapolation/TrkExEngine/python/__init__.py
@@ -0,0 +1,2 @@
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
diff --git a/Tracking/TrkExtrapolation/TrkExEngine/src/ExtrapolationEngine.cxx b/Tracking/TrkExtrapolation/TrkExEngine/src/ExtrapolationEngine.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..d8d583f569c02f95eff87752059d52a76600d351
--- /dev/null
+++ b/Tracking/TrkExtrapolation/TrkExEngine/src/ExtrapolationEngine.cxx
@@ -0,0 +1,111 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// ExtrapolationEngine.cxx, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+// STL
+#include <sstream>
+// Trk include
+#include "TrkExEngine/ExtrapolationEngine.h"
+#include "TrkDetDescrUtils/GeometrySignature.h"
+
+// constructor
+Trk::ExtrapolationEngine::ExtrapolationEngine(const std::string& t, const std::string& n, const IInterface* p)
+: AthAlgTool(t,n,p),
+  m_trackingGeometry(0),
+  m_trackingGeometrySvc("AtlasTrackingGeometrySvc", n),
+  m_trackingGeometryName("AtlasTrackingGeometry"),
+  m_forceSearchInit(false)
+{
+    declareInterface<Trk::IExtrapolationEngine>(this);
+    
+    // Geometry retrieval
+    declareProperty("TrackingGeometrySvc"                   , m_trackingGeometrySvc);
+    // Extrapolation Engine retrieval 
+    declareProperty("ExtrapolationEngines"                  , m_extrapolationEngines);
+    // Material Updator Engine retrival
+    
+    // steering of the screen outoput (SOP)
+    declareProperty("OutputPrefix"                          , m_sopPrefix);
+    declareProperty("OutputPostfix"                         , m_sopPostfix);
+    // the properties to be given 
+    declareProperty("ForceSearchAtInit"                     , m_forceSearchInit);
+}
+
+// destructor
+Trk::ExtrapolationEngine::~ExtrapolationEngine()
+{}
+
+
+// the interface method initialize
+StatusCode Trk::ExtrapolationEngine::initialize()
+{
+
+            
+    EX_MSG_INFO( "init", " starting initialize()" );
+
+    // get the TrackingGeometrySvc
+    if (m_trackingGeometrySvc.retrieve().isSuccess()){
+        EX_MSG_INFO( "init", "Successfully retrieved " << m_trackingGeometrySvc );
+        m_trackingGeometryName = m_trackingGeometrySvc->trackingGeometryName();
+    } else {
+        EX_MSG_WARNING( "init", "Couldn't retrieve " << m_trackingGeometrySvc << ". " );
+        EX_MSG_WARNING( "init", " -> Trying to retrieve default '" << m_trackingGeometryName << "' from DetectorStore. Abort." );
+        return StatusCode::FAILURE;
+    }
+    
+    // retrieve the ExtrapolationEngines
+    if (m_extrapolationEngines.retrieve().isFailure()){
+        
+    } else {
+        EX_MSG_INFO( "init", "Successfully retrieved " << m_extrapolationEngines.size() << " ExtrapolationEngines. Ordering them now." );
+        m_eeAccessor = std::vector<const Trk::IExtrapolationEngine*>(int(Trk::NumberOfGeometryTypes), (const Trk::IExtrapolationEngine*)NULL);
+        for (auto& ee : m_extrapolationEngines){
+            EX_MSG_DEBUG( "init", "Registering " << ee->name() << " - for GeometryType : "  << ee->geometryType() );
+            m_eeAccessor[ee->geometryType()] = (&*ee);
+        }
+    }
+    
+    
+    
+    return StatusCode::SUCCESS;
+}    
+
+// the interface method finalize
+StatusCode Trk::ExtrapolationEngine::finalize()
+{    
+    EX_MSG_INFO( "fini", "finalize() successful" );    
+    return StatusCode::SUCCESS;
+}
+
+
+/** charged extrapolation */
+Trk::ExtrapolationCode Trk::ExtrapolationEngine::extrapolate(ExCellCharged& ecCharged,
+                                                        const Surface* sf,
+                                                        PropDirection dir,
+                                                        BoundaryCheck bcheck) const
+{ return extrapolateT<TrackParameters>(ecCharged,sf,dir,bcheck); }
+
+
+/** neutral extrapolation */
+Trk::ExtrapolationCode Trk::ExtrapolationEngine::extrapolate(ExCellNeutral& ecNeutral,
+                                                        const Surface* sf,
+                                                        PropDirection dir,
+                                                        BoundaryCheck bcheck) const
+{ return extrapolateT<NeutralParameters>(ecNeutral,sf,dir,bcheck); }
+                                           
+
+StatusCode Trk::ExtrapolationEngine::updateTrackingGeometry() const {
+    // retrieve the TrackingGeometry from the detector store 
+    if (detStore()->retrieve(m_trackingGeometry, m_trackingGeometryName).isFailure()){
+        EX_MSG_FATAL( "tgeo", "Could not retrieve TrackingGeometry '" << m_trackingGeometryName << "' from DetectorStore." );
+        EX_MSG_FATAL( "tgeo", "  - probably the chosen layout is not supported / no cool tag exists. "                     );
+        return StatusCode::FAILURE;
+    }
+    return StatusCode::SUCCESS;
+}
+
+
diff --git a/Tracking/TrkExtrapolation/TrkExEngine/src/MaterialEffectsEngine.cxx b/Tracking/TrkExtrapolation/TrkExEngine/src/MaterialEffectsEngine.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..158cd4dc8a71457b49dac7f470b55af3b11734cb
--- /dev/null
+++ b/Tracking/TrkExtrapolation/TrkExEngine/src/MaterialEffectsEngine.cxx
@@ -0,0 +1,145 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// MaterialEffectsEngine.cxx, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+// STL
+#include <sstream>
+// Trk include
+#include "TrkExEngine/MaterialEffectsEngine.h"
+#include "TrkGeometry/Layer.h"
+
+// constructor
+Trk::MaterialEffectsEngine::MaterialEffectsEngine(const std::string& t, const std::string& n, const IInterface* p)
+: AthAlgTool(t,n,p)
+{
+    declareInterface<Trk::IMaterialEffectsEngine>(this);
+    // steering of the screen outoput (SOP)
+    declareProperty("OutputPrefix"                          , m_sopPrefix);
+    declareProperty("OutputPostfix"                         , m_sopPostfix);
+}
+
+// destructor
+Trk::MaterialEffectsEngine::~MaterialEffectsEngine()
+{}
+
+
+// the interface method initialize
+StatusCode Trk::MaterialEffectsEngine::initialize()
+{
+    EX_MSG_INFO( "init", " starting initialize()" );
+    return StatusCode::SUCCESS;
+}    
+
+// the interface method finalize
+StatusCode Trk::MaterialEffectsEngine::finalize()
+{    
+    EX_MSG_INFO( "fini", "finalize() successful" );    
+    return StatusCode::SUCCESS;
+}
+
+
+/** charged extrapolation */
+Trk::ExtrapolationCode Trk::MaterialEffectsEngine::handleMaterial(Trk::ExCellCharged& eCell,
+                                                                  Trk::PropDirection dir,
+                                                                  Trk::MaterialUpdateStage matupstage) const
+{
+
+    // the Extrapolator made sure that the layer is the lead layer && the parameters are the lead parameters
+    if (eCell.leadLayer && eCell.leadLayer->layerMaterialProperties()){
+        EX_MSG_DEBUG(++eCell.navigationStep, "handleMaterial for charged TrackParameters called."); 
+        // update the track parameters    
+        eCell.leadParameters = updateTrackParameters(*eCell.leadParameters,eCell,dir,matupstage);
+    }
+    return Trk::ExtrapolationCode::InProgress;
+}
+
+/** charged extrapolation */
+const Trk::TrackParameters* Trk::MaterialEffectsEngine::updateTrackParameters(const Trk::TrackParameters& parameters,
+                                                                              Trk::ExCellCharged& eCell,
+                                                                              Trk::PropDirection dir,
+                                                                              Trk::MaterialUpdateStage matupstage) const 
+{
+    // now calculate the pathCorrection from the layer surface - it is signed, gives you the relative direction to the layer
+    const Trk::Layer* layer = eCell.leadLayer;
+    // path correction 
+    double pathCorrection = layer->surfaceRepresentation().pathCorrection(parameters.position(),dir*(parameters.momentum()));
+    // the relative direction wrt with the layer
+    Trk::PropDirection rlDir = (pathCorrection > 0. ? Trk::alongMomentum : Trk::oppositeMomentum);
+    // multiply by the pre-and post-update factor
+    double mFactor = layer->layerMaterialProperties()->factor(rlDir, matupstage);
+    if (mFactor == 0.){
+        EX_MSG_VERBOSE(eCell.navigationStep, "material update with pre/post update factor 0. No update done."); 
+        // return the parameters untouched -
+        return (&parameters);
+    }
+    pathCorrection = mFactor*pathCorrection;
+    // screen output
+    EX_MSG_VERBOSE(eCell.navigationStep, "material update on layer with index " << layer->layerIndex().value() << " - corr factor = " << pathCorrection); 
+    // get the actual material bin
+    const Trk::MaterialProperties* materialProperties = layer->layerMaterialProperties()->fullMaterial(parameters.position());
+    // and let's check if there's acutally something to do
+    if (materialProperties){
+        // a simple cross-check if the parameters are the initial ones
+        AmgVector(5)      uParameters = parameters.parameters();
+        AmgSymMatrix(5)*  uCovariance = parameters.covariance() ? new AmgSymMatrix(5)(*parameters.covariance()) : 0;
+        // get the material itself & its parameters
+        const Trk::Material& material = materialProperties->material();
+        double thicknessInX0          = materialProperties->thicknessInX0();
+        double thickness              = materialProperties->thickness();
+        // calculate energy loss and multiple scattering
+        double p      = parameters.momentum().mag();
+        double m      = m_particleMasses.mass[eCell.pHypothesis];
+        double E      = sqrt(p*p+m*m);
+        double beta   = p/E;
+        double sigmaP = 0.;
+        double kazL   = 0.;
+        /** dE/dl ionization energy loss per path unit */
+        double dEdX = m_interactionFormulae.dEdl_ionization(p, &material, eCell.pHypothesis, sigmaP, kazL);    
+        double dE   = dEdX*thickness*pathCorrection;
+        // calcuate the new momentum
+        double newP = sqrt((E+dE)*(E+dE)-m*m);
+        uParameters[Trk::qOverP] = parameters.charge()/newP;
+        // @TODO add straggling
+        
+        // update the covariance if needed
+        if (uCovariance){
+            /** multiple scattering as function of dInX0 */
+            double sigmaMS = m_interactionFormulae.sigmaMS(thicknessInX0*pathCorrection, p, beta);    
+            double sinTheta = sin(parameters.parameters()[Trk::theta]);
+            double sigmaDeltaPhiSq = sigmaMS*sigmaMS/(sinTheta*sinTheta);
+            double sigmaDeltaThetaSq = sigmaMS*sigmaMS;
+            // and add them 
+            int sign = int(eCell.materialUpdateMode);
+            // add or remove @TODO implement check for covariance matrix -> 0
+            (*uCovariance)(Trk::phi,Trk::phi)      += sign*sigmaDeltaPhiSq;
+            (*uCovariance)(Trk::theta, Trk::theta) += sign*sigmaDeltaThetaSq;
+        }
+        // check if material filling was requested
+        if (eCell.checkConfigurationMode(Trk::ExtrapolationMode::CollectMaterial)){
+            EX_MSG_VERBOSE(eCell.navigationStep, "collecting material at layer " << layer->layerIndex().value() << " of - t/X0 = " << thicknessInX0); 
+            eCell.stepMaterial(parameters.associatedSurface(), layer, parameters.position(), pathCorrection, materialProperties);
+        }
+        // now either create new ones or update - only start parameters can not be updated
+        if (eCell.leadParameters != eCell.startParameters ){
+            EX_MSG_VERBOSE(eCell.navigationStep, "material update on non-initial parameters."); 
+            parameters.updateParameters(uParameters,uCovariance);
+        } else {
+            EX_MSG_VERBOSE(eCell.navigationStep, "material update on initial parameters, creating new ones."); 
+            // create new parameters
+            const Trk::Surface& tSurface = parameters.associatedSurface();
+            const Trk::TrackParameters* tParameters = tSurface.createTrackParameters(uParameters[Trk::loc1],
+                                                                                     uParameters[Trk::loc2],
+                                                                                     uParameters[Trk::phi],
+                                                                                     uParameters[Trk::theta],
+                                                                                     uParameters[Trk::qOverP],
+                                                                                     uCovariance);
+             // these are newly created                                                                                     
+             return tParameters;                                                                                                                                         
+        }                
+    }        
+    return (&parameters);
+}
diff --git a/Tracking/TrkExtrapolation/TrkExEngine/src/PropagationEngine.cxx b/Tracking/TrkExtrapolation/TrkExEngine/src/PropagationEngine.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..87973d6a19e9ee0eff9aed4e95f6fd818bacb65f
--- /dev/null
+++ b/Tracking/TrkExtrapolation/TrkExEngine/src/PropagationEngine.cxx
@@ -0,0 +1,164 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// PropagationEngine.cxx, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+// STL
+#include <sstream>
+// Trk include
+#include "TrkExEngine/PropagationEngine.h"
+#include "TrkExInterfaces/IPropagator.h"
+#include "TrkSurfaces/Surface.h"
+
+// constructor
+Trk::PropagationEngine::PropagationEngine(const std::string& t, const std::string& n, const IInterface* p)
+: AthAlgTool(t,n,p),
+  m_propagator(""),
+  m_pathLimitTolerance(0.01)
+{
+    declareInterface<Trk::IPropagationEngine>(this);
+    // configure the Propagator
+    declareProperty("Propagator"                            , m_propagator);
+    // steering of the screen outoput (SOP)
+    declareProperty("OutputPrefix"                          , m_sopPrefix);
+    declareProperty("OutputPostfix"                         , m_sopPostfix);
+    // the path limit tolerance
+    declareProperty("PathLimitTolerance"                    , m_pathLimitTolerance);
+}
+
+// destructor
+Trk::PropagationEngine::~PropagationEngine()
+{}
+
+
+// the interface method initialize
+StatusCode Trk::PropagationEngine::initialize()
+{
+    
+    if (m_propagator.retrieve().isFailure()){
+        EX_MSG_FATAL( "init", "failed to retrieve propagator '"<< m_propagator << "'. Aborting." );
+        return StatusCode::FAILURE;
+    } else 
+        EX_MSG_INFO( "init", "successfully retrieved '" << m_propagator << "'." );
+
+    EX_MSG_INFO( "init", "initialize() successful" );
+    return StatusCode::SUCCESS;
+}    
+
+// the interface method finalize
+StatusCode Trk::PropagationEngine::finalize()
+{    
+    EX_MSG_INFO( "fini", "finalize() successful" );    
+    return StatusCode::SUCCESS;
+}
+
+
+/** resolve the boundary situation - for charged particles */
+Trk::ExtrapolationCode Trk::PropagationEngine::propagate(Trk::ExCellCharged& eCell,
+                                                         const Trk::Surface& sf,
+                                                         Trk::PropDirection pDir,
+                                                         Trk::BoundaryCheck bcheck,
+                                                         bool returnCurvilinear) const
+{
+    EX_MSG_DEBUG(++eCell.navigationStep, "propagation engine called with charged parameters with propagation direciton " << pDir ); 
+
+    double propLength = -1.;
+    if (eCell.checkConfigurationMode(Trk::ExtrapolationMode::StopWithPathLimit)){
+        // the path limit
+        propLength = eCell.pathLimit > 0 ? (eCell.pathLimit-eCell.pathLength) : eCell.pathLimit;
+        EX_MSG_VERBOSE(eCell.navigationStep, "available step length for this propagation " << propLength ); 
+    }
+    // it is the final propagation if it is the endSurface
+    bool finalPropagation = (eCell.endSurface == (&sf));
+    //
+    Trk::TransportJacobian* tjac = 0;
+    // we need to first fill the propagation parameters in order to be able to updates & fallbacks
+    const Trk::TrackParameters* pParameters = m_propagator->propagate(*eCell.leadParameters, 
+                                                                      sf,
+                                                                      pDir,
+                                                                      bcheck,
+                                                                      eCell.mFieldMode,
+                                                                      tjac,
+                                                                      propLength,
+                                                                      eCell.pHypothesis,
+                                                                      returnCurvilinear);
+   // set the return type according to how the propagation went
+   if (pParameters){
+       // assign the lead and end parameters
+       eCell.leadParameters = pParameters;
+       // check what to do with the path Length
+       if (eCell.checkConfigurationMode(Trk::ExtrapolationMode::StopWithPathLimit) || propLength > 0){
+           // add the new propagation length to the path length
+           eCell.pathLength += propLength;
+           // check if Limit reached
+           if (eCell.pathLimitReached(m_pathLimitTolerance)){
+               EX_MSG_VERBOSE(eCell.navigationStep, "path limit of " << eCell.pathLimit << " successfully reached -> stopping." ); 
+               return Trk::ExtrapolationCode::SuccessPathLimit;
+           }
+       }
+       // return Success only if it is the final propagation - the extrapolation engine knows that 
+       return (finalPropagation ? Trk::ExtrapolationCode::SuccessDestination : Trk::ExtrapolationCode::InProgress);
+   }                                                                      
+   // return - recovered means that the leadParameters are the input ones 
+   return (finalPropagation ? Trk::ExtrapolationCode::FailureDestination : Trk::ExtrapolationCode::Recovered) ;
+}
+
+/** resolve the boundary situation - for neutral particles */
+Trk::ExtrapolationCode Trk::PropagationEngine::propagate(Trk::ExCellNeutral& eCell,
+                                                         const Trk::Surface& sf,
+                                                         Trk::PropDirection pDir,
+                                                         Trk::BoundaryCheck bcheck,
+                                                         bool returnCurvilinear) const
+{ 
+    EX_MSG_DEBUG(++eCell.navigationStep, "propagation engine called with neutral parameters with propagation direciton " << pDir );     
+    // leave this for the moment, can re replaced by an appropriate propagator call later
+    if (eCell.leadParameters->covariance()){
+        EX_MSG_VERBOSE(eCell.navigationStep, "propagation of neutral parameters with covariances requested. This is not supported for the moment."); 
+    }
+    // the pathLimit cache so far
+    double cPath = eCell.pathLength;
+    // it is the final propagation if it is the endSurface
+    bool finalPropagation = (eCell.endSurface == (&sf));
+    // intersect the surface
+    Trk::Intersection sfIntersection = pDir ? sf.straightLineIntersection(eCell.leadParameters->position(),
+                                                                          pDir*eCell.leadParameters->momentum().unit(),
+                                                                          true, bcheck) :
+                                              sf.straightLineIntersection(eCell.leadParameters->position(),
+                                              eCell.leadParameters->momentum().unit(),
+                                              false, bcheck); 
+    // we have a valid intersection                                 
+    if (sfIntersection.valid){
+        // fill the transport information - only if the propation direction is not 0
+        if (pDir){
+           double pLength = (sfIntersection.position-eCell.leadParameters->position()).mag(); 
+           EX_MSG_VERBOSE(eCell.navigationStep, "Path length of " << pLength << " added to the extrapolation cell (limit = " << eCell.pathLimit << ")" );    
+           eCell.stepTransport(sf,pLength);
+        }
+        // now check if it is valud it's further away than the pathLimit
+        if (eCell.pathLimitReached(m_pathLimitTolerance)){
+            // create new neutral curvilinear parameters at the path limit reached 
+            double pDiff = eCell.pathLimit - cPath;
+            eCell.leadParameters = new Trk::NeutralCurvilinearParameters(eCell.leadParameters->position()+pDiff*eCell.leadParameters->momentum().unit(), 
+                                                                         eCell.leadParameters->momentum(),
+                                                                         0.);
+            EX_MSG_VERBOSE(eCell.navigationStep, "path limit of " << eCell.pathLimit << " reached. Stopping extrapolation."); 
+            return Trk::ExtrapolationCode::SuccessPathLimit;
+        }  
+        // now exchange the lead parameters 
+        // create the new curvilinear paramters at the surface intersection -> if so, trigger the success
+        eCell.leadParameters = returnCurvilinear ? new Trk::NeutralCurvilinearParameters(sfIntersection.position, eCell.leadParameters->momentum(), 0.) :
+                                                       sf.createNeutralParameters(sfIntersection.position, eCell.leadParameters->momentum(), 0.);
+
+        // return success for the final destination or in progress                                                                   
+        return (finalPropagation ? Trk::ExtrapolationCode::SuccessDestination : Trk::ExtrapolationCode::InProgress);
+
+    } else {
+        // give some screen output
+        EX_MSG_VERBOSE(eCell.navigationStep, "intersection with the surface did not succeed.");
+    }                                                                     
+   // return - recovered means that the leadParameters are the input ones 
+   return (finalPropagation ? Trk::ExtrapolationCode::FailureDestination : Trk::ExtrapolationCode::Recovered) ;
+}
diff --git a/Tracking/TrkExtrapolation/TrkExEngine/src/StaticEngine.cxx b/Tracking/TrkExtrapolation/TrkExEngine/src/StaticEngine.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..7a8b90113f05c1f65a4361505a10238435f78a99
--- /dev/null
+++ b/Tracking/TrkExtrapolation/TrkExEngine/src/StaticEngine.cxx
@@ -0,0 +1,84 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// StaticEngine.cxx, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+// STL
+#include <sstream>
+// Trk include
+#include "TrkExEngine/StaticEngine.h"
+
+// constructor
+Trk::StaticEngine::StaticEngine(const std::string& t, const std::string& n, const IInterface* p)
+: AthAlgTool(t,n,p),
+  m_propagationEngine(""),          
+  m_navigationEngine(""),    
+  m_materialEffectsEngine("")  
+{
+    declareInterface<Trk::IExtrapolationEngine>(this);
+    // The Tools needed
+    declareProperty("PropagationEngine"                     , m_propagationEngine);
+    declareProperty("NavigationEngine"                      , m_navigationEngine);
+    declareProperty("MaterialEffectsEngine"                 , m_materialEffectsEngine);
+    // steering of the screen outoput (SOP)
+    declareProperty("OutputPrefix"                          , m_sopPrefix);
+    declareProperty("OutputPostfix"                         , m_sopPostfix);
+}
+
+// destructor
+Trk::StaticEngine::~StaticEngine()
+{}
+
+
+// the interface method initialize
+StatusCode Trk::StaticEngine::initialize()
+{
+    EX_MSG_INFO( "init", "initialize()" );
+    
+    if (m_propagationEngine.retrieve().isFailure()){
+        EX_MSG_FATAL( "init", "failed to retrieve propagation engine '"<< m_propagationEngine << "'. Aborting." );
+        return StatusCode::FAILURE;
+    } else 
+        EX_MSG_INFO( "init", "successfully  propagation engine '" << m_propagationEngine << "'." );
+    
+    if (m_navigationEngine.retrieve().isFailure()){
+        EX_MSG_FATAL( "init", "failed to retrieve navigation engine '"<< m_navigationEngine << "'. Aborting." );
+        return StatusCode::FAILURE;
+    } else 
+        EX_MSG_INFO( "init", "successfully retrieved '" << m_navigationEngine << "'." );
+            
+    if (m_materialEffectsEngine.retrieve().isFailure()){
+        EX_MSG_FATAL( "init", "failed to retrieve material effect engine '"<< m_materialEffectsEngine << "'. Aborting." );
+        return StatusCode::FAILURE;
+    } else 
+        EX_MSG_INFO( "init", "successfully retrieved '" << m_materialEffectsEngine << "'." );
+    
+    return StatusCode::SUCCESS;
+}    
+
+// the interface method finalize
+StatusCode Trk::StaticEngine::finalize()
+{    
+    ATH_MSG_INFO( "finalize() successful" );    
+    return StatusCode::SUCCESS;
+}
+
+
+/** charged extrapolation */
+Trk::ExtrapolationCode Trk::StaticEngine::extrapolate(ExCellCharged& ecCharged,
+                                           const Surface* sf,
+                                           PropDirection dir,
+                                           BoundaryCheck bcheck) const
+{ return extrapolateT<TrackParameters>(ecCharged,sf,dir,bcheck); }
+
+
+/** neutral extrapolation */
+Trk::ExtrapolationCode Trk::StaticEngine::extrapolate(ExCellNeutral& ecNeutral,
+                                           const Surface* sf,
+                                           PropDirection dir,
+                                           BoundaryCheck bcheck) const
+{ return extrapolateT<NeutralParameters>(ecNeutral,sf,dir,bcheck); }
+                                           
\ No newline at end of file
diff --git a/Tracking/TrkExtrapolation/TrkExEngine/src/StaticNavigationEngine.cxx b/Tracking/TrkExtrapolation/TrkExEngine/src/StaticNavigationEngine.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..685aa5ccc6549a7a3769d2602ed03e1532160d2b
--- /dev/null
+++ b/Tracking/TrkExtrapolation/TrkExEngine/src/StaticNavigationEngine.cxx
@@ -0,0 +1,82 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// StaticNavigationEngine.cxx, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+// STL
+#include <sstream>
+// Trk include
+#include "TrkExEngine/StaticNavigationEngine.h"
+
+// constructor
+Trk::StaticNavigationEngine::StaticNavigationEngine(const std::string& t, const std::string& n, const IInterface* p)
+: AthAlgTool(t,n,p),
+  m_propagationEngine(""),
+  m_materialEffectsEngine(""),
+  m_trackingGeometry(0),
+  m_trackingGeometryName("AtlasTrackingGeometry")
+  
+{
+    declareInterface<Trk::INavigationEngine>(this);
+    // Tools needed
+    declareProperty("PropagationEngine"                     , m_propagationEngine);
+    declareProperty("MaterialEffectsEngine"                 , m_materialEffectsEngine);
+    // The TrackingGeometry
+    declareProperty("TrackingGeometry"                      , m_trackingGeometryName);
+    // steering of the screen outoput (SOP)
+    declareProperty("OutputPrefix"                          , m_sopPrefix);
+    declareProperty("OutputPostfix"                         , m_sopPostfix);
+}
+
+// destructor
+Trk::StaticNavigationEngine::~StaticNavigationEngine()
+{}
+
+// the interface method initialize
+StatusCode Trk::StaticNavigationEngine::initialize()
+{
+    EX_MSG_INFO( "init", "initialize()" );
+    
+    if (m_propagationEngine.retrieve().isFailure()){
+        EX_MSG_FATAL( "init", "failed to retrieve propagation engine '"<< m_propagationEngine << "'. Aborting." );
+        return StatusCode::FAILURE;
+    } else 
+        EX_MSG_INFO( "init", "successfully retrieved '" << m_propagationEngine << "'." );
+    
+    if (m_materialEffectsEngine.retrieve().isFailure()){
+        EX_MSG_FATAL( "init", "failed to retrieve material effect engine '"<< m_materialEffectsEngine << "'. Aborting." );
+        return StatusCode::FAILURE;
+    } else 
+        EX_MSG_INFO( "init", "successfully retrieved '" << m_materialEffectsEngine << "'." );
+    
+    return StatusCode::SUCCESS;
+}    
+
+// the interface method finalize
+StatusCode Trk::StaticNavigationEngine::finalize()
+{    
+    ATH_MSG_INFO( "finalize() successful" );    
+    return StatusCode::SUCCESS;
+}
+
+/** charged situation */
+Trk::ExtrapolationCode Trk::StaticNavigationEngine::resolveBoundary(Trk::ExCellCharged& ecCharged, PropDirection dir) const
+{ return resolveBoundaryT<Trk::TrackParameters>(ecCharged,dir); }
+
+/** charged situation */
+Trk::ExtrapolationCode Trk::StaticNavigationEngine::resolveBoundary(Trk::ExCellNeutral& ecNeutral, PropDirection dir) const
+{ return resolveBoundaryT<Trk::NeutralParameters>(ecNeutral,dir); }
+
+StatusCode Trk::StaticNavigationEngine::updateTrackingGeometry() const {
+    // retrieve the TrackingGeometry from the detector store 
+    if (detStore()->retrieve(m_trackingGeometry, m_trackingGeometryName).isFailure()){
+        EX_MSG_FATAL( "tgeo", "Could not retrieve TrackingGeometry '" << m_trackingGeometryName << "' from DetectorStore." );
+        EX_MSG_FATAL( "tgeo", "  - probably the chosen layout is not supported / no cool tag exists. "                     );
+        return StatusCode::FAILURE;
+    }
+    return StatusCode::SUCCESS;
+}
+
diff --git a/Tracking/TrkExtrapolation/TrkExEngine/src/components/TrkExEngine_entries.cxx b/Tracking/TrkExtrapolation/TrkExEngine/src/components/TrkExEngine_entries.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..315bf68aaa445b3b6e890031898bdef6b327acb3
--- /dev/null
+++ b/Tracking/TrkExtrapolation/TrkExEngine/src/components/TrkExEngine_entries.cxx
@@ -0,0 +1,26 @@
+#include "GaudiKernel/DeclareFactoryEntries.h"
+#include "TrkExEngine/ExtrapolationEngine.h"
+#include "TrkExEngine/StaticEngine.h"
+#include "TrkExEngine/StaticNavigationEngine.h"
+#include "TrkExEngine/MaterialEffectsEngine.h"
+#include "TrkExEngine/PropagationEngine.h"
+
+using namespace Trk;
+
+DECLARE_TOOL_FACTORY( ExtrapolationEngine )
+DECLARE_TOOL_FACTORY( MaterialEffectsEngine )
+DECLARE_TOOL_FACTORY( StaticEngine )
+DECLARE_TOOL_FACTORY( StaticNavigationEngine )
+DECLARE_TOOL_FACTORY( PropagationEngine )
+
+/** factory entries need to have the name of the package */
+DECLARE_FACTORY_ENTRIES( TrkExEngine )
+{
+    DECLARE_TOOL( ExtrapolationEngine )
+    DECLARE_TOOL( MaterialEffectsEngine )        
+    DECLARE_TOOL( StaticEngine )
+    DECLARE_TOOL( StaticNavigationEngine )
+    DECLARE_TOOL( PropagationEngine )
+}
+
+
diff --git a/Tracking/TrkExtrapolation/TrkExEngine/src/components/TrkExEngine_load.cxx b/Tracking/TrkExtrapolation/TrkExEngine/src/components/TrkExEngine_load.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..563e2d8a5549da993596bbb0c212d350ff499269
--- /dev/null
+++ b/Tracking/TrkExtrapolation/TrkExEngine/src/components/TrkExEngine_load.cxx
@@ -0,0 +1,4 @@
+#include "GaudiKernel/LoadFactoryEntries.h"
+
+LOAD_FACTORY_ENTRIES( TrkExEngine )
+