From 53d45fc9315fe661511fccd2a8be8736a03e31d5 Mon Sep 17 00:00:00 2001
From: Dave Casper <dcasper@uci.edu>
Date: Mon, 4 Feb 2019 22:59:12 -0800
Subject: [PATCH] Adapt GeoModelSvc and related components to FASER

---
 CMakeLists.txt                                |   2 +
 .../GeoModel/FaserGeoModel/data/geomDB.sql    |  22 +-
 .../GeoModelInterfaces/CMakeLists.txt         |  15 +
 .../GeoModelInterfaces/AbsMaterialManager.h   |  49 +
 .../GeoModelInterfaces/IGeoAlignTool.h        |  41 +
 .../GeoModelInterfaces/IGeoDbTagSvc.h         |  49 +
 .../GeoModelInterfaces/IGeoModelSvc.h         |  67 ++
 .../GeoModelInterfaces/IGeoModelTool.h        |  38 +
 .../GeoModelInterfaces/IGeoSubDetTool.h       |  37 +
 .../StoredMaterialManager.h                   |  58 ++
 .../GeoModel/GeoModelSvc/CMakeLists.txt       |  41 +
 .../GeoModel/GeoModelSvc/src/GeoDbTagSvc.cxx  | 110 ++
 .../GeoModel/GeoModelSvc/src/GeoDbTagSvc.h    |  74 ++
 .../GeoModel/GeoModelSvc/src/GeoModelSvc.cxx  | 576 +++++++++++
 .../GeoModel/GeoModelSvc/src/GeoModelSvc.h    | 112 ++
 .../GeoModelSvc/src/RDBMaterialManager.cxx    | 961 ++++++++++++++++++
 .../GeoModelSvc/src/RDBMaterialManager.h      |  94 ++
 .../src/components/GeoModelSvc_entries.cxx    |   6 +
 18 files changed, 2351 insertions(+), 1 deletion(-)
 create mode 100644 DetectorDescription/GeoModel/GeoModelInterfaces/CMakeLists.txt
 create mode 100644 DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/AbsMaterialManager.h
 create mode 100644 DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoAlignTool.h
 create mode 100644 DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoDbTagSvc.h
 create mode 100644 DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoModelSvc.h
 create mode 100644 DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoModelTool.h
 create mode 100644 DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoSubDetTool.h
 create mode 100644 DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/StoredMaterialManager.h
 create mode 100644 DetectorDescription/GeoModel/GeoModelSvc/CMakeLists.txt
 create mode 100644 DetectorDescription/GeoModel/GeoModelSvc/src/GeoDbTagSvc.cxx
 create mode 100644 DetectorDescription/GeoModel/GeoModelSvc/src/GeoDbTagSvc.h
 create mode 100644 DetectorDescription/GeoModel/GeoModelSvc/src/GeoModelSvc.cxx
 create mode 100644 DetectorDescription/GeoModel/GeoModelSvc/src/GeoModelSvc.h
 create mode 100644 DetectorDescription/GeoModel/GeoModelSvc/src/RDBMaterialManager.cxx
 create mode 100644 DetectorDescription/GeoModel/GeoModelSvc/src/RDBMaterialManager.h
 create mode 100644 DetectorDescription/GeoModel/GeoModelSvc/src/components/GeoModelSvc_entries.cxx

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0fafefc1b..165d96d02 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,6 +3,8 @@ cmake_minimum_required(VERSION 3.6)
 set( ATLAS_PROJECT Athena
    CACHE STRING	   "The name of the project to build against" )
 
+set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
+
 find_package( Athena )
 
 atlas_ctest_setup()
diff --git a/DetectorDescription/GeoModel/FaserGeoModel/data/geomDB.sql b/DetectorDescription/GeoModel/FaserGeoModel/data/geomDB.sql
index 0f946e431..c1084b35a 100644
--- a/DetectorDescription/GeoModel/FaserGeoModel/data/geomDB.sql
+++ b/DetectorDescription/GeoModel/FaserGeoModel/data/geomDB.sql
@@ -170,6 +170,18 @@ CREATE TABLE IF NOT EXISTS "SCINTMATCOMPONENTS_DATA2TAG" (
 	"SCINTMATCOMPONENTS_TAG_ID" SLONGLONG,
 	"SCINTMATCOMPONENTS_DATA_ID" SLONGLONG
 );
+DROP TABLE IF EXISTS "FASERCOMMON_DATA";
+CREATE TABLE IF NOT EXISTS "FASERCOMMON_DATA" ( 
+	"FASERCOMMON_DATA_ID" SLONGLONG UNIQUE,
+	"CONFIG" TEXT ,
+	"GEOTYPE" TEXT ,
+	"STRIPGEOTYPE" TEXT 
+);
+DROP TABLE IF EXISTS "FASERCOMMON_DATA2TAG";
+CREATE TABLE IF NOT EXISTS "FASERCOMMON_DATA2TAG" (
+	"FASERCOMMON_TAG_ID" SLONGLONG,
+	"FASERCOMMON_DATA_ID" SLONGLONG
+);
 --
 -- Part 2a: HVS data
 --
@@ -187,8 +199,9 @@ INSERT INTO "HVS_NODE" VALUES (1001, "ScintPlate", 1, 0, NULL);
 INSERT INTO "HVS_NODE" VALUES (1002, "ScintStation", 1, 0, NULL);
 INSERT INTO "HVS_NODE" VALUES (1003, "ScintMaterials", 1, 0, NULL);
 INSERT INTO "HVS_NODE" VALUES (1004, "ScintMatComponents", 1, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (110,  "FaserCommon", 0, 0, NULL);
 -- Data for the HVS_TAG2NODE table
-INSERT INTO "HVS_TAG2NODE" VALUES (0, "FASER-00", 100000, NULL, 0, 0, 1549238400000000000, NULL, 0);
+INSERT INTO "HVS_TAG2NODE" VALUES (0, "FASER-00", 100000, NULL, 0, 0, 1549238400000000000, NULL, 1);
 INSERT INTO "HVS_TAG2NODE" VALUES (1, "Scintillator-00", 100001, NULL, 0, 0, 1549238400000000000, NULL, 1);
 INSERT INTO "HVS_TAG2NODE" VALUES (2, "Tracker-00", 100002, NULL, 0, 0, 1549238400000000000, NULL, 1);
 INSERT INTO "HVS_TAG2NODE" VALUES (3, "Calorimeter-00", 100003, NULL, 0, 0, 1549238400000000000, NULL, 1);
@@ -201,6 +214,7 @@ INSERT INTO "HVS_TAG2NODE" VALUES (1001, "ScintPlate-00", 100009, NULL, 0, 0, 15
 INSERT INTO "HVS_TAG2NODE" VALUES (1002, "ScintStation-00", 100010, NULL, 0, 0, 1549238400000000000, NULL, 1);
 INSERT INTO "HVS_TAG2NODE" VALUES (1003, "ScintMaterials-00", 100011, NULL, 0, 0, 1549238400000000000, NULL, 1);
 INSERT INTO "HVS_TAG2NODE" VALUES (1004, "ScintMatComponents-00", 100012, NULL, 0, 0, 1549238400000000000, NULL, 1);
+INSERT INTO "HVS_TAG2NODE" VALUES (110,  "FaserCommon-00", 100013, NULL, 0, 0, 1549324800000000000, NULL, 1);
 -- Data for the HVS_LTAG2LTAG table
 INSERT INTO "HVS_LTAG2LTAG" VALUES (0,   100000, 1,    100001);
 INSERT INTO "HVS_LTAG2LTAG" VALUES (0,   100000, 2,    100002);
@@ -214,6 +228,7 @@ INSERT INTO "HVS_LTAG2LTAG" VALUES (1,   100001, 1001, 100009);
 INSERT INTO "HVS_LTAG2LTAG" VALUES (1,   100001, 1002, 100010);
 INSERT INTO "HVS_LTAG2LTAG" VALUES (1,   100001, 1003, 100011);
 INSERT INTO "HVS_LTAG2LTAG" VALUES (1,   100001, 1004, 100012);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (0,   100000, 110,  100013);
 -- Data for the HVS_TAGCACHE table
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "FASER",              "FASER-00",              100000);
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "Scintillator",       "Scintillator-00",       100001);
@@ -228,6 +243,7 @@ INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "ScintPlate",         "ScintPlate
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "ScintStation",       "ScintStation-00",       100010);
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "ScintMaterials",     "ScintMaterials-00",     100011);
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "ScintMatComponents", "ScintMatComponents-00", 100012);
+INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "FaserCommon",        "FaserCommon-00",        100013);
 -- 
 --
 -- Part 2b: Content (Leaf node) data
@@ -787,4 +803,8 @@ INSERT INTO "SCINTMATCOMPONENTS_DATA" VALUES (0, 0, "Carbon", 0.475);
 INSERT INTO "SCINTMATCOMPONENTS_DATA" VALUES (1, 0, "Hydrogen", 0.525);
 INSERT INTO "SCINTMATCOMPONENTS_DATA2TAG" VALUES (100012, 0);
 INSERT INTO "SCINTMATCOMPONENTS_DATA2TAG" VALUES (100012, 1);
+--
+--
+INSERT INTO "FASERCOMMON_DATA" VALUES (0, "RUN3", "UNDEFINED", "UNDEFINED");
+INSERT INTO "FASERCOMMON_DATA2TAG" VALUES (100013, 0);
 COMMIT;
diff --git a/DetectorDescription/GeoModel/GeoModelInterfaces/CMakeLists.txt b/DetectorDescription/GeoModel/GeoModelInterfaces/CMakeLists.txt
new file mode 100644
index 000000000..9240ff541
--- /dev/null
+++ b/DetectorDescription/GeoModel/GeoModelInterfaces/CMakeLists.txt
@@ -0,0 +1,15 @@
+################################################################################
+# Package: GeoModelInterfaces
+################################################################################
+
+# Declare the package name:
+atlas_subdir( GeoModelInterfaces )
+
+# Declare the package's dependencies:
+atlas_depends_on_subdirs( PUBLIC
+                          Control/AthenaKernel
+                          GaudiKernel )
+
+# Install files from the package:
+atlas_install_headers( GeoModelInterfaces )
+
diff --git a/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/AbsMaterialManager.h b/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/AbsMaterialManager.h
new file mode 100644
index 000000000..5d32183e3
--- /dev/null
+++ b/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/AbsMaterialManager.h
@@ -0,0 +1,49 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef GEOMODELINTERFACES_ABSMATERIALMANAGER_H
+#define GEOMODELINTERFACES_ABSMATERIALMANAGER_H
+//---------------------------------------------------------//
+//                                                         //
+// class AbsMaterialManager  abstract base class for a     //
+// material manager.                                       //
+//                                                         //
+// Joe Boudreau March 2003                                 //
+//                                                         //
+//---------------------------------------------------------//
+#include <string>
+#include <iostream>
+#include <iosfwd>
+
+class GeoMaterial;
+class GeoElement;
+class AbsMaterialManager {
+
+ public:
+
+  // Constructor:
+  AbsMaterialManager() {};
+  
+  // Destructor:
+  virtual ~AbsMaterialManager() {};
+
+  // Query the material:
+  virtual       GeoMaterial *getMaterial(const std::string & name)       =0;
+  virtual const GeoMaterial *getMaterial(const std::string & name) const =0;
+
+  // Query the elements:
+  virtual       GeoElement *getElement(const std::string & name)       = 0;
+  virtual const GeoElement *getElement(const std::string & name) const = 0;
+
+  // Query the elements (by atomic number):
+  virtual       GeoElement *getElement(unsigned int atomicNumber)       = 0;
+  virtual const GeoElement *getElement(unsigned int atomicNumber) const = 0;
+
+  virtual std::ostream & printAll(std::ostream & o=std::cout) const = 0;
+
+
+};
+
+
+#endif
diff --git a/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoAlignTool.h b/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoAlignTool.h
new file mode 100644
index 000000000..9a321391f
--- /dev/null
+++ b/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoAlignTool.h
@@ -0,0 +1,41 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// *****************************************************************************
+// **
+// ** This abstract interface is used by CaloDetDescr/CaloAlignTool.
+// ** The main purpose of this interface is to register align() function
+// ** as a callback on Cond DB objects at initialization time.
+// ** GeoModelSvc instantiates CaloAlignTool after GeoModelSvc::align() has
+// ** been registered, by this way it is guaranteed that 
+// ** CaloAlignTool::align() gets called after LArDetectorTool::align() and
+// ** TileDetectorTool::align()
+// **
+// *****************************************************************************
+
+#ifndef GEOMODELINTERFACES_IGEOALIGNTOOL_H
+#define GEOMODELINTERFACES_IGEOALIGNTOOL_H
+
+#include "GaudiKernel/IAlgTool.h"
+#include "AthenaKernel/IOVSvcDefs.h"
+
+static const InterfaceID IID_IGeoAlignTool( "IGeoAlignTool", 1, 0 );
+
+class IGeoAlignTool : virtual public IAlgTool
+{
+public:
+
+  /// Retrieve Interface ID
+  static const InterfaceID& interfaceID() { return IID_IGeoAlignTool; }
+
+  virtual StatusCode align(IOVSVC_CALLBACK_ARGS) = 0;
+};
+
+ 
+#endif 
+
+
+
+
+
diff --git a/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoDbTagSvc.h b/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoDbTagSvc.h
new file mode 100644
index 000000000..7b7a6722a
--- /dev/null
+++ b/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoDbTagSvc.h
@@ -0,0 +1,49 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef GEOMODELINTERFACES_IGEODBTAGSVC_H
+#define GEOMODELINTERFACES_IGEODBTAGSVC_H
+
+// Include Files
+#include "GaudiKernel/IInterface.h"
+#include <string>
+
+namespace GeoModel {
+  enum GeoConfig {
+    GEO_RUN1,
+    GEO_RUN2,
+    GEO_RUN3,
+    GEO_RUN4,
+    GEO_ITk,
+    GEO_TESTBEAM
+  };
+}  
+
+static const InterfaceID IID_IGeoDbTagSvc("IGeoDbTagSvc", 1, 0);
+
+class IGeoDbTagSvc : virtual public IInterface {
+ public:
+  // Retrieve interface ID
+  static const InterfaceID& interfaceID() {return IID_IGeoDbTagSvc;}
+
+  virtual const std::string & faserVersion()                    const =0;
+  virtual const std::string & scintVersion()                    const =0;
+  // virtual const std::string & SCT_Version()                     const =0;
+  // virtual const std::string & caloVersion()                     const =0;
+  // virtual const std::string & magFieldVersion()                 const =0;
+  // virtual const std::string & cavernInfraVersion()              const =0;
+  
+  virtual const std::string & scintVersionOverride()            const =0;
+  // virtual const std::string & SCT_VersionOverride()             const =0;
+  // virtual const std::string & caloVersionOverride()             const =0;
+  // virtual const std::string & magFieldVersionOverride()         const =0;
+  // virtual const std::string & cavernInfraVersionOverride()      const =0;
+  
+  virtual GeoModel::GeoConfig geoConfig() const = 0;
+};
+
+#endif // GEOMODELINTERFACES_IGEODBTAGSVC_H
+
+
+
diff --git a/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoModelSvc.h b/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoModelSvc.h
new file mode 100644
index 000000000..a6bda8e05
--- /dev/null
+++ b/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoModelSvc.h
@@ -0,0 +1,67 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef GEOMODELINTERFACES_IGEOMODELSVC_H
+#define GEOMODELINTERFACES_IGEOMODELSVC_H
+
+// Include Files
+#include "GeoModelInterfaces/IGeoDbTagSvc.h"
+#include "GaudiKernel/IInterface.h"
+#include "GaudiKernel/StatusCode.h"
+#include "AthenaKernel/IOVSvcDefs.h"
+#include <string>
+
+// Forward declarations
+class IIncidentListener;
+class Incident;
+class IGeoModelTool;
+
+class IGeoModelSvc : virtual public IInterface {
+
+public:
+
+    /// Retrieve interface ID
+  static const InterfaceID& interfaceID();
+
+
+    virtual const std::string & faserVersion()         const =0;
+    virtual const std::string & scintVersion()         const =0;
+    // virtual const std::string & SCT_Version()          const =0;
+    // virtual const std::string & caloVersion()          const =0;
+    // virtual const std::string & magFieldVersion()      const =0;
+    // virtual const std::string & cavernInfraVersion()   const =0;
+
+    virtual const std::string & scintVersionOverride() const =0;
+    // virtual const std::string & SCT_VersionOverride()  const =0;
+    // virtual const std::string & caloVersionOverride()  const =0;
+    // virtual const std::string & magFieldVersionOverride()    const =0;
+    // virtual const std::string & cavernInfraVersionOverride() const =0;
+    
+    virtual GeoModel::GeoConfig geoConfig() const = 0;
+
+    // Callback functions
+    virtual StatusCode align       (IOVSVC_CALLBACK_ARGS) = 0;
+    virtual StatusCode compareTags (IOVSVC_CALLBACK_ARGS) = 0;
+
+    // Access to subsystem tool for callback registration
+    virtual const IGeoModelTool* getTool(std::string toolName) const = 0;
+
+    // Release GeoModel tree from memory
+    virtual StatusCode clear() = 0;
+};
+
+inline
+const InterfaceID&
+IGeoModelSvc::interfaceID() {
+
+  static const InterfaceID IID(1011, 1, 1);
+
+  return IID;
+}
+
+
+#endif // GEOMODELINTERFACES_GEOMODELSVC_H
+
+
+
diff --git a/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoModelTool.h b/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoModelTool.h
new file mode 100644
index 000000000..307d858b2
--- /dev/null
+++ b/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoModelTool.h
@@ -0,0 +1,38 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef GEOMODELINTERFACES_IGEOMODELTOOL_H
+#define GEOMODELINTERFACES_IGEOMODELTOOL_H
+
+#include "GaudiKernel/IAlgTool.h"
+#include "AthenaKernel/IOVSvcDefs.h"
+
+static const InterfaceID IID_IGeoModelTool( "IGeoModelTool", 1, 0 );
+
+class IGeoModelTool : public virtual IAlgTool {
+public:
+
+    /// Retrieve Interface ID
+    static const InterfaceID& interfaceID( ) { return IID_IGeoModelTool; }
+
+    // Abstract interface method(s)
+    virtual StatusCode create() = 0;
+
+    // This method is designed to perform following tasks:
+    //    1. Release detector manager from the Detector Store
+    //    2. Do any extra clean up tasks if necessary
+    virtual StatusCode clear() = 0;
+
+    // Register callback function on ConDB object
+    virtual StatusCode registerCallback() = 0;
+
+    // Callback function itself
+    virtual StatusCode align(IOVSVC_CALLBACK_ARGS) = 0;
+	
+};
+
+#endif // GEOMODELINTERFACES_IGEOMODELTOOL_H
+
+
+
diff --git a/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoSubDetTool.h b/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoSubDetTool.h
new file mode 100644
index 000000000..52437ad15
--- /dev/null
+++ b/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoSubDetTool.h
@@ -0,0 +1,37 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef GEOMODELINTERFACES_IGEOSUBDETTOOL_H
+#define GEOMODELINTERFACES_IGEOSUBDETTOOL_H
+
+#include "GaudiKernel/IAlgTool.h"
+#include "AthenaKernel/IOVSvcDefs.h"
+
+class StoreGateSvc;
+class GeoVPhysVol;
+
+static const InterfaceID IID_IGeoSubDetTool( "IGeoSubDetTool", 1, 0 );
+
+class IGeoSubDetTool : public virtual IAlgTool {
+public:
+
+    /// Retrieve Interface ID
+    static const InterfaceID& interfaceID( ) { return IID_IGeoSubDetTool; }
+  
+
+    // Build subdetector in parent 
+    virtual StatusCode build( GeoVPhysVol* parent ) = 0;
+
+    // Register callback function on ConDB object
+    virtual StatusCode registerCallback( StoreGateSvc* detStore ) = 0;
+  
+    // Callback function itself
+    virtual StatusCode align(IOVSVC_CALLBACK_ARGS) = 0;
+
+};
+
+#endif // GEOMODELINTERFACES_IGEOSUBDETTOOL_H
+
+
+
diff --git a/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/StoredMaterialManager.h b/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/StoredMaterialManager.h
new file mode 100644
index 000000000..f988dacd2
--- /dev/null
+++ b/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/StoredMaterialManager.h
@@ -0,0 +1,58 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef GEOMODELINTERFACES_STOREDMATERIALMANAGER_H
+#define GEOMODELINTERFACES_STOREDMATERIALMANAGER_H
+//---------------------------------------------------------//
+//                                                         //
+// class StoredMaterialManager  This class hold one or more//
+// material managers and makes them storeable, under       //
+// storegate:                                              //
+//                                                         //
+// Joe Boudreau March 2003                                 //
+//                                                         //
+//---------------------------------------------------------//
+#include "GeoModelInterfaces/AbsMaterialManager.h"
+#include "AthenaKernel/CLASS_DEF.h"
+#include <map>
+class StoredMaterialManager:public AbsMaterialManager 
+{
+ public:
+  typedef std::map<std::string, GeoMaterial* > MaterialMap;
+  typedef MaterialMap::const_iterator MaterialMapIterator;
+
+  // Constructor:
+  StoredMaterialManager() {};
+  
+  // Destructor:
+  virtual ~StoredMaterialManager() {};
+
+  // Query the material:
+  virtual       GeoMaterial* getMaterial(const std::string& name)       = 0;
+  virtual const GeoMaterial* getMaterial(const std::string& name) const = 0;
+
+  // Query the elements:
+  virtual       GeoElement* getElement(const std::string& name)       = 0;
+  virtual const GeoElement* getElement(const std::string& name) const = 0;
+
+  // Query the elements (by atomic number):
+  virtual       GeoElement* getElement(unsigned int atomicNumber)       = 0;
+  virtual const GeoElement* getElement(unsigned int atomicNumber) const = 0;
+
+  // Add new material
+  virtual void addMaterial(const std::string& space, GeoMaterial* material)       = 0;
+  virtual void addMaterial(const std::string& space, GeoMaterial* material) const = 0;
+
+  virtual MaterialMapIterator begin() const = 0;
+  virtual MaterialMapIterator end() const = 0;
+
+  // Number of materials in the manager
+  virtual size_t size() = 0;
+
+  virtual std::ostream& printAll(std::ostream & o=std::cout) const = 0;
+};
+
+CLASS_DEF(StoredMaterialManager, 9896,1)
+
+#endif
diff --git a/DetectorDescription/GeoModel/GeoModelSvc/CMakeLists.txt b/DetectorDescription/GeoModel/GeoModelSvc/CMakeLists.txt
new file mode 100644
index 000000000..2ae87919c
--- /dev/null
+++ b/DetectorDescription/GeoModel/GeoModelSvc/CMakeLists.txt
@@ -0,0 +1,41 @@
+################################################################################
+# Package: GeoModelSvc
+################################################################################
+
+# Declare the package name:
+atlas_subdir( GeoModelSvc )
+
+# Declare the package's dependencies:
+atlas_depends_on_subdirs( PRIVATE
+                          Control/CxxUtils
+                          Control/AthenaBaseComps
+                          Control/AthenaKernel
+                          Control/SGTools
+                          Control/StoreGate
+                          Database/RDBAccessSvc
+                          DetectorDescription/GeoModel/GeoModelInterfaces
+                          DetectorDescription/GeoModel/GeoModelUtilities
+                          Event/EventInfo
+                          Event/EventInfoMgt
+                          GaudiKernel )
+
+# External dependencies:
+find_package( Boost COMPONENTS filesystem thread system )
+find_package( CORAL COMPONENTS CoralBase CoralKernel RelationalAccess )
+
+
+find_package( GeoModel )
+
+# Component(s) in the package:
+atlas_add_component( GeoModelSvc
+                     src/GeoModelSvc.cxx
+                     src/GeoDbTagSvc.cxx
+                     src/RDBMaterialManager.cxx
+                     src/components/GeoModelSvc_entries.cxx
+                     INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${CORAL_INCLUDE_DIRS} ${GEOMODEL_INCLUDE_DIRS}
+                     LINK_LIBRARIES ${Boost_LIBRARIES} ${CORAL_LIBRARIES} ${GEOMODEL_LIBRARIES} AthenaBaseComps CxxUtils AthenaKernel SGTools StoreGateLib SGtests GeoModelUtilities EventInfo GaudiKernel )
+
+# Install files from the package:
+atlas_install_headers( GeoModelSvc )
+atlas_install_joboptions( share/*.py )
+
diff --git a/DetectorDescription/GeoModel/GeoModelSvc/src/GeoDbTagSvc.cxx b/DetectorDescription/GeoModel/GeoModelSvc/src/GeoDbTagSvc.cxx
new file mode 100644
index 000000000..f0ba30fbd
--- /dev/null
+++ b/DetectorDescription/GeoModel/GeoModelSvc/src/GeoDbTagSvc.cxx
@@ -0,0 +1,110 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "GeoDbTagSvc.h"
+#include "RDBMaterialManager.h"
+#include "GaudiKernel/ServiceHandle.h"
+
+#include "RDBAccessSvc/IRDBAccessSvc.h"
+#include "RDBAccessSvc/IRDBRecordset.h"
+#include "RDBAccessSvc/IRDBRecord.h"
+
+GeoDbTagSvc::GeoDbTagSvc(const std::string& name,ISvcLocator* svc)
+  : AthService(name,svc)
+  , m_geoConfig(GeoModel::GEO_RUN3)
+{
+}
+
+GeoDbTagSvc::~GeoDbTagSvc()
+{
+}
+
+StatusCode GeoDbTagSvc::initialize()
+{
+  ATH_MSG_DEBUG("initialize()");
+  return StatusCode::SUCCESS;
+}
+
+StatusCode GeoDbTagSvc::finalize()
+{
+  ATH_MSG_DEBUG("finalize()");
+  return StatusCode::SUCCESS;
+}
+
+// Query the interfaces.
+//   Input: riid, Requested interface ID
+//          ppvInterface, Pointer to requested interface
+//   Return: StatusCode indicating SUCCESS or FAILURE.
+// N.B. Don't forget to release the interface after use!!!
+StatusCode GeoDbTagSvc::queryInterface(const InterfaceID& riid, void** ppvInterface)
+{
+  if(IGeoDbTagSvc::interfaceID().versionMatch(riid)) {
+    *ppvInterface = (IGeoDbTagSvc*)this;
+    addRef();
+    return StatusCode::SUCCESS;
+  } else  {
+    // Interface is not directly available: try out a base class
+    return AthService::queryInterface(riid, ppvInterface);
+  }
+}
+
+StatusCode GeoDbTagSvc::setupTags()
+{
+  ATH_MSG_DEBUG("setupTags()");
+  
+  // Check if the Atlas version has already been set
+  if(m_FaserVersion.empty()) {
+    ATH_MSG_FATAL("FASER tag not set!");
+    return StatusCode::FAILURE;
+  }
+  
+  // Get RDBAccessSvc
+  ServiceHandle<IRDBAccessSvc> rdbAccessSvc("RDBAccessSvc", name());
+  if(rdbAccessSvc.retrieve().isFailure()) {
+    ATH_MSG_FATAL("Failed to retrieve RDBAccessSvc");
+    return StatusCode::FAILURE;
+  }
+
+  // Get subsystem tags
+  m_ScintVersion = (m_ScintVersionOverride.empty() 
+		    ? rdbAccessSvc->getChildTag("Scintillator", m_FaserVersion, "FASER") 
+		    : m_ScintVersionOverride);
+
+  // m_SCT_Version = (m_SCT_VersionOverride.empty()
+	// 	   ? rdbAccessSvc->getChildTag("SCT",m_InDetVersion,"InnerDetector")
+	// 	   : m_SCT_VersionOverride);
+
+  // m_CaloVersion = (m_CaloVersionOverride.empty()
+  //                  ? rdbAccessSvc->getChildTag("Calorimeter",m_AtlasVersion,"ATLAS")
+	// 	   : m_CaloVersionOverride);
+
+  // m_MagFieldVersion = (m_MagFieldVersionOverride.empty()
+	// 	       ? rdbAccessSvc->getChildTag("MagneticField",m_AtlasVersion,"ATLAS")
+	// 	       : m_MagFieldVersionOverride);
+
+  // m_CavernInfraVersion = (m_CavernInfraVersionOverride.empty()
+	// 		  ? rdbAccessSvc->getChildTag("CavernInfra",m_AtlasVersion,"ATLAS")
+	// 		  : m_CavernInfraVersionOverride);
+
+  // Retrieve geometry config information (RUN1, RUN2, etc...)
+  IRDBRecordset_ptr faserCommonRec = rdbAccessSvc->getRecordsetPtr("FaserCommon", m_FaserVersion, "FASER");
+  if(faserCommonRec->size()==0) {
+    m_geoConfig = GeoModel::GEO_RUN3;
+  }
+  else {
+    std::string configVal = (*faserCommonRec)[0]->getString("CONFIG");
+    if(configVal=="RUN3")
+      m_geoConfig = GeoModel::GEO_RUN3;
+    else if(configVal=="RUN4")
+      m_geoConfig = GeoModel::GEO_RUN4;
+    else if(configVal=="TESTBEAM")
+      m_geoConfig = GeoModel::GEO_TESTBEAM;
+    else {
+      ATH_MSG_FATAL("Unexpected value for geometry config read from the database: " << configVal);
+      return StatusCode::FAILURE;
+    }
+  }
+
+  return StatusCode::SUCCESS;
+}
diff --git a/DetectorDescription/GeoModel/GeoModelSvc/src/GeoDbTagSvc.h b/DetectorDescription/GeoModel/GeoModelSvc/src/GeoDbTagSvc.h
new file mode 100644
index 000000000..f31902469
--- /dev/null
+++ b/DetectorDescription/GeoModel/GeoModelSvc/src/GeoDbTagSvc.h
@@ -0,0 +1,74 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef GEOMODELSVC_GEODBTAGSVC_H
+#define GEOMODELSVC_GEODBTAGSVC_H
+
+#include "GeoModelInterfaces/IGeoDbTagSvc.h"
+#include "AthenaBaseComps/AthService.h"
+
+template <class TYPE> class SvcFactory;
+
+class GeoDbTagSvc : public AthService, virtual public IGeoDbTagSvc
+{
+  friend class GeoModelSvc;
+
+ public:
+  virtual StatusCode initialize();
+  virtual StatusCode finalize();
+
+  virtual StatusCode queryInterface( const InterfaceID& riid, void** ppvInterface );
+
+  friend class SvcFactory<GeoDbTagSvc>;
+
+  GeoDbTagSvc(const std::string& name, ISvcLocator* svc);
+  virtual ~GeoDbTagSvc();
+
+ protected:
+
+  void setFaserVersion(const std::string& tag)                     { m_FaserVersion=tag; }
+  void setScintVersionOverride(const std::string& tag)             { m_ScintVersionOverride=tag; }
+  // void setSCT_VersionOverride(const std::string& tag)              { m_SCT_VersionOverride=tag; }
+  // void setCaloVersionOverride(const std::string& tag)              { m_CaloVersionOverride=tag; }
+  // void setMagFieldVersionOverride(const std::string& tag)          { m_MagFieldVersionOverride=tag; }
+  // void setCavernInfraVersionOverride(const std::string& tag)       { m_CavernInfraVersionOverride=tag; }
+
+  StatusCode setupTags();
+
+ private:
+  // ______________________________ IGeoDbTagSvc ____________________________________
+  const std::string & faserVersion()                     const { return m_FaserVersion; }
+  const std::string & scintVersionOverride()             const { return m_ScintVersionOverride; }
+  // const std::string & SCT_VersionOverride()              const { return m_SCT_VersionOverride; }
+  // const std::string & caloVersionOverride()              const { return m_CaloVersionOverride; }
+  // const std::string & magFieldVersionOverride()          const { return m_MagFieldVersionOverride; }
+  // const std::string & cavernInfraVersionOverride()       const { return m_CavernInfraVersionOverride; }
+
+  const std::string & scintVersion()                     const { return m_ScintVersion; }
+  // const std::string & SCT_Version()                      const { return m_SCT_Version; }
+  // const std::string & caloVersion()                      const { return m_CaloVersion; }
+  // const std::string & magFieldVersion()                  const { return m_MagFieldVersion; }
+  // const std::string & cavernInfraVersion()               const { return m_CavernInfraVersion; }
+
+  GeoModel::GeoConfig geoConfig() const { return m_geoConfig; }
+
+  // _________________________ Private data Members _______________________________
+  std::string m_FaserVersion;
+
+  std::string m_ScintVersion;
+  // std::string m_SCT_Version;
+  // std::string m_CaloVersion;
+  // std::string m_MagFieldVersion;
+  // std::string m_CavernInfraVersion;
+
+  std::string m_ScintVersionOverride;
+  // std::string m_SCT_VersionOverride;
+  // std::string m_CaloVersionOverride;
+  // std::string m_MagFieldVersionOverride;
+  // std::string m_CavernInfraVersionOverride;
+
+  GeoModel::GeoConfig m_geoConfig;
+};
+
+#endif // GEOMODELSVC_GEODBTAGSVC_H
diff --git a/DetectorDescription/GeoModel/GeoModelSvc/src/GeoModelSvc.cxx b/DetectorDescription/GeoModel/GeoModelSvc/src/GeoModelSvc.cxx
new file mode 100644
index 000000000..5ebef7092
--- /dev/null
+++ b/DetectorDescription/GeoModel/GeoModelSvc/src/GeoModelSvc.cxx
@@ -0,0 +1,576 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "GeoModelKernel/GeoBox.h"
+#include "GeoModelKernel/GeoLogVol.h"
+#include "GeoModelKernel/GeoPhysVol.h"
+#include "GeoModelKernel/GeoMaterial.h" 
+#include "GeoModelKernel/GeoVolumeCursor.h"
+#include "GeoModelUtilities/GeoModelExperiment.h"
+#include "GeoModelSvc.h"
+#include "RDBMaterialManager.h"
+#include "GeoDbTagSvc.h"
+#include "GeoModelInterfaces/IGeoAlignTool.h"
+#include "GaudiKernel/ISvcLocator.h"
+#include "GaudiKernel/IConversionSvc.h"
+#include "GaudiKernel/SystemOfUnits.h"
+#include "CxxUtils/make_unique.h"
+
+#include "RDBAccessSvc/IRDBAccessSvc.h"
+#include "RDBAccessSvc/IRDBRecordset.h"
+#include "RDBAccessSvc/IRDBRecord.h"
+
+#include "EventInfo/TagInfo.h"
+
+#include "GeoModelKernel/GeoPerfUtils.h"
+#include <fstream>
+
+#include "AthenaKernel/ClassID_traits.h"
+#include "SGTools/DataProxy.h"
+
+GeoModelSvc::GeoModelSvc(const std::string& name,ISvcLocator* svc)
+  : AthService(name,svc),
+    m_detectorTools(this), 
+    m_pSvcLocator(svc),
+    m_toolSvc("ToolSvc",name),
+    m_detStore("DetectorStore",name),
+    m_tagInfoMgr("TagInfoMgr",name),
+    m_geoDbTagSvc("GeoDbTagSvc",name),
+    m_FaserVersion("AUTO"),
+    m_printMaterials(false),
+    m_callBackON(true),
+    m_ignoreTagDifference(false),
+    m_useTagInfo(true),
+    m_useCaloAlign(false),
+    m_statisticsToFile(false),
+    m_supportedGeometry(0),
+    m_ignoreTagSupport(false)
+{
+  declareProperty( "DetectorTools",               m_detectorTools);
+  declareProperty( "PrintMaterials",              m_printMaterials);
+  declareProperty( "FaserVersion",                m_FaserVersion);
+  declareProperty( "ScintVersionOverride",        m_ScintVersionOverride);
+  // declareProperty( "SCT_VersionOverride",         m_SCT_VersionOverride);
+  // declareProperty( "CaloVersionOverride",         m_CaloVersionOverride);
+  // declareProperty( "MagFieldVersionOverride",     m_MagFieldVersionOverride);
+  // declareProperty( "CavernInfraVersionOverride",  m_CavernInfraVersionOverride);
+  declareProperty( "AlignCallbacks",              m_callBackON);
+  declareProperty( "IgnoreTagDifference",         m_ignoreTagDifference);
+  declareProperty( "UseTagInfo",                  m_useTagInfo);
+  declareProperty( "StatisticsToFile",            m_statisticsToFile);
+  declareProperty( "SupportedGeometry",           m_supportedGeometry);
+  declareProperty( "IgnoreTagSupport",            m_ignoreTagSupport);
+}
+
+GeoModelSvc::~GeoModelSvc()
+{
+}
+
+StatusCode GeoModelSvc::initialize()
+{
+  if(m_supportedGeometry==0) {
+    ATH_MSG_FATAL("The Supported Geometry flag was not set in Job Options! Exiting ...");
+    return StatusCode::FAILURE;
+  }
+
+  ATH_CHECK( m_detStore.retrieve() );
+  ATH_CHECK( m_toolSvc.retrieve() );
+
+  // --- Sebastien
+  // clients (detector tools) are assuming the DetDescrCnvSvc has been
+  // correctly initialized.
+  // We ensure this is indeed correct by manually initialize it so there is
+  // no more service-ordering problem triggered by jobO mix-up
+  ServiceHandle<IConversionSvc> conversionSvc("DetDescrCnvSvc", this->name());
+  ATH_CHECK( conversionSvc.retrieve() );
+  // --- Sebastien
+
+  ATH_CHECK( m_detectorTools.retrieve() );
+
+  ToolHandleArray< IGeoModelTool >::iterator itPriv = m_detectorTools.begin(),
+    itPrivEnd = m_detectorTools.end();
+
+  // **** **** **** TagInfo **** **** ****
+  std::string tagInfoKey = "";
+
+  if(m_useTagInfo) {
+    // get the key
+    ATH_CHECK( m_tagInfoMgr.retrieve() );
+    tagInfoKey = m_tagInfoMgr->tagInfoKey();
+  }
+
+  // build regular geometry
+  ATH_CHECK( geoInit() );
+
+  if(!m_callBackON) {
+    // _________________ Align functions NOT registered as callbacks _____________
+
+    // Apply possible alignments to detectors.
+    // Dummy parameters for the callback
+    int par1 = 0;
+    std::list<std::string> par2;
+    for(; itPriv!=itPrivEnd; ++itPriv) {
+      if((*itPriv)->align(par1,par2) != StatusCode::SUCCESS) {
+        ATH_MSG_DEBUG("align() failed for the tool " << (*itPriv)->name());
+      }
+    }
+    
+    // Fill in the contents of TagInfo
+    if(m_useTagInfo) {
+      ATH_CHECK(fillTagInfo());
+    }
+  }
+  else {
+    // _________________ Align functions NOT registered as callbacks _____________
+
+    // We want to register IGeoModelSvc::align() even if no alignment callback is registered by
+    // subsystem tools, such that clients like CaloTowerBuilder can simply go after IGeoModelSvc::align()
+    bool alignRegistered = false;
+
+    // Register align() functions for all Tools 
+    for (; itPriv!=itPrivEnd; ++itPriv) {
+      IGeoModelTool* theTool = &(**itPriv);
+	
+      if(StatusCode::SUCCESS != theTool->registerCallback()) {
+        ATH_MSG_DEBUG("IGeoModelTool::align() was not registerred on CondDB object for the tool " << theTool->name());
+      }
+      else {
+        if(StatusCode::SUCCESS == m_detStore->regFcn(&IGeoModelTool::align,theTool,
+						      &IGeoModelSvc::align,dynamic_cast<IGeoModelSvc*>(this))) {
+          ATH_MSG_DEBUG("IGeoModelSvc::align() callback registered for the tool " << theTool->name());
+          alignRegistered = true;
+
+          // Set useCaloAlign flag if the successful tool is LAr
+          if((*itPriv).typeAndName().find("LAr")!=std::string::npos) {
+              m_useCaloAlign = true;
+          }
+        }
+        else {
+          ATH_MSG_DEBUG("Unable to register callback on IGeoModelSvc::align() for the tool " << theTool->name());
+        }
+      }
+    }
+
+    // Retrieve a tool for Calo Alignments
+    if(m_useCaloAlign) {
+      IGeoAlignTool* calo_align{nullptr};
+      if(m_toolSvc->retrieveTool("CaloAlignTool",calo_align)!=StatusCode::SUCCESS) {
+        ATH_MSG_INFO("Unable to retrieve CaloAlignTool. No Calo alignments in this job");
+      }
+      else {
+        ATH_MSG_DEBUG("CaloAligntTool retrieved successfully");
+      }
+    }
+
+    // Register a callback on TagInfo in order to compare geometry configurations defined in job options
+    // to the one read from the input file
+    if(m_useTagInfo) {
+      const DataHandle<TagInfo> tagInfoH;
+      if(m_detStore->regFcn(&IGeoModelSvc::compareTags,dynamic_cast<IGeoModelSvc*>(this), tagInfoH, tagInfoKey) != StatusCode::SUCCESS) {
+        ATH_MSG_WARNING("Cannot register compareTags function for key "  << tagInfoKey);
+      }
+      else {
+        ATH_MSG_DEBUG("Registered compareTags callback for key: " << tagInfoKey);
+	
+        if(!alignRegistered) {
+	  // There is no successfull alignment callback registration from subsystems
+	  // Register IGeoModelSvc::align() after IGeoModelSvc::compareTags() then
+          if(m_detStore->regFcn(&IGeoModelSvc::compareTags,dynamic_cast<IGeoModelSvc*>(this),
+              &IGeoModelSvc::align,dynamic_cast<IGeoModelSvc*>(this)) == StatusCode::SUCCESS) {
+            ATH_MSG_DEBUG("Registered IGeoModelSvc::align() after IGeoModelSvc::compareTags()");
+          }
+          else {
+            ATH_MSG_WARNING("Cannot register IGeoModelSvc::align() after IGeoModelSvc::compareTags()");
+          }
+        }
+      }
+
+      // Fill in the contents of TagInfo
+      ATH_CHECK(fillTagInfo());
+    }
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+StatusCode GeoModelSvc::finalize()
+{
+  return StatusCode::SUCCESS;
+}
+
+// Query the interfaces.
+//   Input: riid, Requested interface ID
+//          ppvInterface, Pointer to requested interface
+//   Return: StatusCode indicating SUCCESS or FAILURE.
+// N.B. Don't forget to release the interface after use!!!
+StatusCode GeoModelSvc::queryInterface(const InterfaceID& riid, void** ppvInterface)
+{
+  if(IGeoModelSvc::interfaceID().versionMatch(riid)) {
+    *ppvInterface = (IGeoModelSvc*)this;
+    addRef();
+    return StatusCode::SUCCESS;
+  } 
+  else {
+    // Interface is not directly available: try out a base class
+    return AthService::queryInterface(riid, ppvInterface);
+  }
+}
+
+StatusCode GeoModelSvc::geoInit()
+{
+  ATH_MSG_DEBUG("** Building geometry configuration: ");
+  ATH_MSG_DEBUG("* FASER tag: " << m_FaserVersion);
+  ATH_MSG_DEBUG("* Scint tag: " << m_ScintVersionOverride);
+  // ATH_MSG_DEBUG("* SCT   tag: " << m_SCT_VersionOverride);
+  // ATH_MSG_DEBUG("* Calo  tag: " << m_CaloVersionOverride);
+  // ATH_MSG_DEBUG("* MagField  tag: " << m_MagFieldVersionOverride);
+  // ATH_MSG_DEBUG("* CavernInfra  tag: " << m_CavernInfraVersionOverride);
+  
+  // GetRDBAccessSvc and open connection to DB
+  ServiceHandle<IRDBAccessSvc> rdbAccess("RDBAccessSvc",name());
+  ATH_CHECK( rdbAccess.retrieve() );
+
+  if(!rdbAccess->connect()) {
+    ATH_MSG_ERROR("Unable to connect to the Geometry DB");
+    return StatusCode::FAILURE;
+  }
+
+  // Check the existence of FASER tag in the database
+  if(rdbAccess->getChildTag("FASER",m_FaserVersion,"FASER")=="") {
+    ATH_MSG_FATAL(" *** *** Wrong FASER layout: " << m_FaserVersion << " *** ***");
+    ATH_MSG_FATAL(" Either FASER geometry tag has been misspelled, or the DB Release does not contain the geometry specified.");
+    ATH_MSG_FATAL(" In latter case please update DB Release version");
+    return StatusCode::FAILURE;
+  }
+
+  if(!m_ignoreTagSupport) {
+    RDBTagDetails faserTagDetails = rdbAccess->getTagDetails(m_FaserVersion);
+    const coral::AttributeSpecification& supportedSpec = faserTagDetails["SUPPORTED"].specification();
+    if(supportedSpec.type()==typeid(bool)) {
+      if(!faserTagDetails["SUPPORTED"].data<bool>()) {
+	      ATH_MSG_FATAL(" *** *** FASER layout " << m_FaserVersion << " is OBSOLETE and can NOT be supported any more! *** ***");
+	      return StatusCode::FAILURE;
+      }
+    }
+    else if(supportedSpec.type()==typeid(int)) {
+      if(faserTagDetails["SUPPORTED"].data<int>()<m_supportedGeometry) {
+	      ATH_MSG_FATAL(" *** *** FASER layout " << m_FaserVersion 
+		      << " is OBSOLETE in rel " << m_supportedGeometry 
+		      << " and can NOT be supported any more! *** ***");
+	      return StatusCode::FAILURE;
+      }
+    }
+  }
+
+  // Create a material manager
+  StoredMaterialManager *theMaterialManager{nullptr};
+  try{
+    theMaterialManager = new RDBMaterialManager(m_pSvcLocator);
+  }
+  catch(std::runtime_error& e) {
+    ATH_MSG_FATAL(e.what());
+    return StatusCode::FAILURE;
+  }
+  ATH_CHECK( m_detStore->record(theMaterialManager,"MATERIALS") );
+  
+  // Setup the GeoDbTagSvc
+  ATH_CHECK( m_geoDbTagSvc.retrieve() );
+  
+  GeoDbTagSvc* dbTagSvc = dynamic_cast<GeoDbTagSvc*>(m_geoDbTagSvc.operator->());
+  if(dbTagSvc==nullptr) {
+    ATH_MSG_FATAL("Unable to dyn-cast the IGeoDbTagSvc pointer to GeoDbTagSvc");
+    return StatusCode::FAILURE;
+  }
+
+  dbTagSvc->setFaserVersion(m_FaserVersion);
+  dbTagSvc->setScintVersionOverride(m_ScintVersionOverride);
+  // dbTagSvc->setSCT_VersionOverride(m_SCT_VersionOverride);
+  // dbTagSvc->setCaloVersionOverride(m_CaloVersionOverride);
+  // dbTagSvc->setMagFieldVersionOverride(m_MagFieldVersionOverride);
+  // dbTagSvc->setCavernInfraVersionOverride(m_CavernInfraVersionOverride);
+
+  if(dbTagSvc->setupTags().isFailure()) {
+    ATH_MSG_FATAL("Failed to setup subsystem tags");
+    return StatusCode::FAILURE;
+  }
+
+  // Build the world node from which everything else will be suspended
+  const GeoMaterial* air = theMaterialManager->getMaterial("std::Air");  
+  const GeoBox* worldBox = new GeoBox(1000*Gaudi::Units::cm,1000*Gaudi::Units::cm, 1000*Gaudi::Units::cm);
+  const GeoLogVol* worldLog = new GeoLogVol("WorldLog", worldBox, air);
+  GeoPhysVol *worldPhys=new GeoPhysVol(worldLog);
+  
+  // Create FaserExperiment and register it within the transient detector store
+  GeoModelExperiment* theExperiment = new GeoModelExperiment(worldPhys);
+  ATH_CHECK( m_detStore->record(theExperiment,"FASER") );
+
+  int mem,cpu;
+  std::unique_ptr<std::ofstream> geoModelStats;
+  if(m_statisticsToFile) {
+    geoModelStats = CxxUtils::make_unique<std::ofstream>("GeoModelStatistics");
+    *geoModelStats << "Detector Configuration flag = " << m_FaserVersion << std::endl; 
+  }
+    
+  // Loop over all tools
+  ToolHandleArray< IGeoModelTool >::iterator itPriv = m_detectorTools.begin(),
+    itPrivEnd = m_detectorTools.end();
+  
+  for(; itPriv!=itPrivEnd; ++itPriv) {
+    IGeoModelTool* theTool = &(**itPriv);
+      
+    mem = GeoPerfUtils::getMem();
+    cpu = GeoPerfUtils::getCpu();
+      
+    if(theTool->create().isFailure()) {
+      ATH_MSG_ERROR("Unable to create detector " << theTool->name());
+      return StatusCode::FAILURE;
+    }
+      
+    if(m_statisticsToFile) {
+      *geoModelStats << theTool->name() << "\t SZ= " 
+		     << GeoPerfUtils::getMem() - mem << "Kb \t Time = " << (GeoPerfUtils::getCpu() - cpu) * 0.01 << "S" << std::endl;
+    }
+    else {
+      ATH_MSG_INFO(theTool->name() << "\t SZ= " 
+		   << GeoPerfUtils::getMem() - mem << "Kb \t Time = " << (GeoPerfUtils::getCpu() - cpu) * 0.01 << "S");
+    }
+  }
+    
+  if(m_statisticsToFile) {
+    geoModelStats->close();
+  }
+	
+  // Close DB connection
+  rdbAccess->shutdown();
+  if(m_printMaterials)
+    theMaterialManager->printAll();
+  
+  return StatusCode::SUCCESS;
+}
+
+StatusCode GeoModelSvc::align(IOVSVC_CALLBACK_ARGS)
+{
+  ATH_MSG_DEBUG("GeoModelSvc::align() called");
+  return StatusCode::SUCCESS;
+}
+
+StatusCode GeoModelSvc::compareTags(IOVSVC_CALLBACK_ARGS)
+{
+  bool tagsMatch = true;  
+
+  ATH_MSG_DEBUG("GeoModelSvc::compareTags() callback trigerred");
+
+  // Get TagInfo and retrieve tags
+  const TagInfo* tagInfo = 0;
+  ATH_CHECK( m_detStore->retrieve(tagInfo) );
+
+  TagInfo::NameTagPairVec pairs;
+  tagInfo->getInputTags(pairs);
+  for( const auto& pair : pairs ) {
+    std::string tagPairName = pair.first;
+    if(tagPairName=="GeoAtlas") {
+      // ** Two possible cases need to be taken into account
+      // ** 
+      // ** 1. The retrieved FASER tag is following naming schema FASER-...-XX-YY-ZZ
+      // ** where '...' can be anything, it may also containg one or more '-'.
+      // ** If this is the case, then we need to check whether the job option tag
+      // ** is also following the same schema and they have the same 'FASER-...-XX' part
+      // **
+      // ** 2. The retrieved FASER tag is not following the schema mentioned above
+      // ** If this is the case, we just need to check the exact match
+      std::vector<std::string> tokensTagInfo, tokensJobOpt;
+
+      // Parse Tag Info tag
+      std::string::size_type startpos = 0;
+      std::string currStr = pair.second;
+      for(std::string::size_type endpos=currStr.find("-"); endpos!=std::string::npos; endpos=currStr.find("-",startpos)) {
+        tokensTagInfo.push_back(currStr.substr(startpos,endpos-startpos));
+        startpos = endpos+1;
+      }
+      tokensTagInfo.push_back(currStr.substr(startpos));
+      
+      size_t tokensTagInfoSize = tokensTagInfo.size();
+      bool tagInfoFollowsTheScheme = (tokensTagInfoSize>=5 
+				      && tokensTagInfo[tokensTagInfoSize-1].size()==2
+				      && tokensTagInfo[tokensTagInfoSize-2].size()==2
+				      && tokensTagInfo[tokensTagInfoSize-3].size()==2);
+
+      if(tagInfoFollowsTheScheme) {
+        // Parse Job Options tag
+        startpos = 0;
+        currStr = m_FaserVersion;
+        for(std::string::size_type endpos=currStr.find("-"); endpos!=std::string::npos; endpos=currStr.find("-",startpos)) {
+          tokensJobOpt.push_back(currStr.substr(startpos,endpos-startpos));
+          startpos = endpos+1;
+        }
+        tokensJobOpt.push_back(currStr.substr(startpos));
+        
+        size_t tokensJobOptSize = tokensJobOpt.size();
+        bool jobOptFollowsTheScheme = (tokensJobOptSize>=5
+                    && tokensJobOpt[tokensJobOptSize-1].size()==2
+                    && tokensJobOpt[tokensJobOptSize-2].size()==2
+                    && tokensJobOpt[tokensJobOptSize-3].size()==2);
+        if(jobOptFollowsTheScheme) {
+          tagsMatch = (pair.second.substr(0,currStr.size()-6)==m_FaserVersion.substr(0,m_FaserVersion.size()-6));
+        }
+        else {
+          tagsMatch = false;
+        }
+      }
+      else {// Check for the exact match 
+        tagsMatch = m_FaserVersion == pair.second;
+      }
+    }
+    else if(tagPairName=="GeoScint")
+      tagsMatch = m_ScintVersionOverride == pair.second;
+    // else if(tagPairName=="GeoSCT")
+    //   tagsMatch = m_SCT_VersionOverride == pair.second;
+    
+    if(!tagsMatch) break;
+  }
+
+  if(!tagsMatch) {
+    msg((m_ignoreTagDifference? MSG::WARNING : MSG::ERROR)) 
+      << "*** *** Geometry configured through jobOptions does not match TagInfo tags! *** ***" << endmsg;
+    ATH_MSG_INFO("** Job Option configuration: ");
+    ATH_MSG_INFO("* FASER tag: " << m_FaserVersion);
+    ATH_MSG_INFO("* Scint tag: " << m_ScintVersionOverride);
+    // ATH_MSG_INFO("* SCT   tag: " << m_SCT_VersionOverride);
+    // ATH_MSG_INFO("* Calo  tag: " << m_CaloVersionOverride);
+    // ATH_MSG_INFO("* MagField  tag: " << m_MagFieldVersionOverride);
+    // ATH_MSG_INFO("* CavernInfra  tag: " << m_CavernInfraVersionOverride);
+    ATH_MSG_INFO("** TAG INFO configuration: ");
+    for (const auto& pair : pairs) {
+      std::string tagPairName = pair.first;
+      if(tagPairName=="GeoFaser")
+        ATH_MSG_INFO("* FASER tag: " << pair.second);
+      else if(tagPairName=="GeoScint")
+        ATH_MSG_INFO("*Scint  tag: " << pair.second);
+      // else if(tagPairName=="GeoSCT")
+      //   ATH_MSG_INFO("*SCT  tag: " << pair.second);
+      // else if(tagPairName=="GeoCalo")
+      //   ATH_MSG_INFO("*Calo  tag: " << pair.second);
+      // else if(tagPairName=="GeoMagField")
+      //   ATH_MSG_INFO("*MagField  tag: " << pair.second);
+      // else if(tagPairName=="GeoCavernInfra")
+      //   ATH_MSG_INFO("*CavernInfra  tag: " << pair.second);
+    }
+    
+    if(!m_ignoreTagDifference) {
+      ATH_MSG_INFO("*** *** Please fix geometry tag settings *** ***");
+      return StatusCode::FAILURE;
+    }
+  }
+  else
+    ATH_MSG_DEBUG("Geometry configurations in jobOptions and TagInfo are consistent");
+
+  return StatusCode::SUCCESS;
+}
+
+/**********************************************************************************
+ ** Private Member Functions
+ **********************************************************************************/
+StatusCode GeoModelSvc::fillTagInfo() const
+{
+  if(m_FaserVersion == "") {
+    ATH_MSG_ERROR("FASER version is empty");
+    return StatusCode::FAILURE; 
+  }
+  
+  if(m_tagInfoMgr->addTag("GeoFaser",m_FaserVersion).isFailure()) {
+    ATH_MSG_ERROR("GeoModelSvc Faser tag: " << m_FaserVersion	<< " not added to TagInfo ");
+    return StatusCode::FAILURE; 
+  }
+
+  if(m_ScintVersionOverride != "") {
+    if(m_tagInfoMgr->addTag("GeoScint",m_ScintVersionOverride).isFailure()) {
+      ATH_MSG_ERROR("GeoModelSvc Scint tag: " << m_ScintVersionOverride << " not added to TagInfo ");
+      return StatusCode::FAILURE; 
+    }
+  } 
+
+  // if(m_SCT_VersionOverride != "") {
+  //   if(m_tagInfoMgr->addTag("GeoSCT",m_SCT_VersionOverride).isFailure()) {
+  //     ATH_MSG_ERROR("GeoModelSvc SCT tag: " << m_SCT_VersionOverride << " not added to TagInfo ");
+  //     return StatusCode::FAILURE; 
+  //   }
+  // }
+
+  // if(m_CaloVersionOverride != "") {
+  //   if(m_tagInfoMgr->addTag("GeoCalo",m_CaloVersionOverride).isFailure()) {
+  //     ATH_MSG_ERROR("GeoModelSvc Calo tag: " << m_CaloVersionOverride << " not added to TagInfo ");
+  //     return StatusCode::FAILURE; 
+  //   }
+  // }
+
+  // if(m_MagFieldVersionOverride != "") {
+  //   if(m_tagInfoMgr->addTag("GeoMagField",m_MagFieldVersionOverride).isFailure()) {
+  //     ATH_MSG_ERROR("GeoModelSvc MagField tag: " << m_MagFieldVersionOverride << " not added to TagInfo ");
+  //     return StatusCode::FAILURE; 
+  //   }
+  // }
+
+  // if(m_CavernInfraVersionOverride != "") {
+  //   if(m_tagInfoMgr->addTag("GeoCavernInfra",m_CavernInfraVersionOverride).isFailure()) {
+  //     ATH_MSG_ERROR("GeoModelSvc CavernInfra tag: " << m_CavernInfraVersionOverride << " not added to TagInfo ");
+  //     return StatusCode::FAILURE; 
+  //   }
+  // }
+  return StatusCode::SUCCESS;
+}
+
+const IGeoModelTool* GeoModelSvc::getTool(std::string toolName) const
+{
+  ToolHandleArray< IGeoModelTool >::const_iterator itPriv = m_detectorTools.begin();
+
+  for(; itPriv!=m_detectorTools.end(); itPriv++) {
+    const IGeoModelTool* theTool = &(**itPriv);
+    if(theTool->name().find(toolName)!=std::string::npos)
+      return theTool;
+  }
+
+  return 0;
+}
+
+StatusCode GeoModelSvc::clear()
+{
+  ATH_MSG_DEBUG("In clear()"); 
+
+  // Call clear() for all tools
+  ToolHandleArray< IGeoModelTool >::iterator itPriv = m_detectorTools.begin();
+  for(; itPriv!=m_detectorTools.end(); itPriv++) {
+    IGeoModelTool* theTool = &(**itPriv);
+    if(theTool->clear().isFailure()) {
+      ATH_MSG_ERROR("clear() failed for the tool: " << theTool->name());
+      return StatusCode::FAILURE;
+    } else {
+      ATH_MSG_DEBUG(theTool->name() << " tool released");
+    }
+  }
+
+  // Delete GeoModelExperiment - cascade delete of the entire GeoModel tree
+  std::vector<std::string>::const_iterator it;
+  std::vector<std::string> sgkeysExp;
+  m_detStore->keys<GeoModelExperiment>(sgkeysExp);
+  for(it=sgkeysExp.begin(); it!=sgkeysExp.end(); it++) {
+    SG::DataProxy* proxy = m_detStore->proxy(ClassID_traits<GeoModelExperiment>::ID(),*it);
+    if(proxy) {
+      proxy->reset();
+      ATH_MSG_DEBUG(*it << " GeoModel experiment released");
+    }
+  }
+
+  // Release stored material manager
+  std::vector<std::string> sgkeysMat;
+  m_detStore->keys<StoredMaterialManager>(sgkeysMat);
+  for(it=sgkeysMat.begin(); it!=sgkeysMat.end(); it++) {
+    SG::DataProxy* proxy = m_detStore->proxy(ClassID_traits<StoredMaterialManager>::ID(),*it);
+    if(proxy) {
+      proxy->reset();
+      ATH_MSG_DEBUG(*it << " material manager released");
+    }
+  }
+
+  return StatusCode::SUCCESS;
+}
diff --git a/DetectorDescription/GeoModel/GeoModelSvc/src/GeoModelSvc.h b/DetectorDescription/GeoModel/GeoModelSvc/src/GeoModelSvc.h
new file mode 100644
index 000000000..ba7a19b56
--- /dev/null
+++ b/DetectorDescription/GeoModel/GeoModelSvc/src/GeoModelSvc.h
@@ -0,0 +1,112 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef GEOMODELSVC_GEOMODELSVC_H
+#define GEOMODELSVC_GEOMODELSVC_H
+
+#include "GeoModelKernel/GeoPVConstLink.h"
+#include "GeoModelInterfaces/IGeoModelSvc.h"
+#include "GeoModelInterfaces/IGeoDbTagSvc.h"
+#include "GeoModelInterfaces/IGeoModelTool.h"
+#include "GaudiKernel/ServiceHandle.h"
+#include "GaudiKernel/IToolSvc.h"
+#include "GaudiKernel/ToolHandle.h"
+#include "GaudiKernel/Property.h"
+#include "AthenaBaseComps/AthService.h"
+#include "StoreGate/StoreGateSvc.h"
+#include "EventInfoMgt/ITagInfoMgr.h"
+#include <fstream>
+
+class ISvcLocator;
+
+template <class TYPE> class SvcFactory;
+
+class GeoModelSvc : public AthService, virtual public IGeoModelSvc {
+
+public:
+
+    virtual StatusCode initialize();
+    virtual StatusCode finalize();
+
+    // Query the interfaces.
+    //   Input: riid, Requested interface ID
+    //          ppvInterface, Pointer to requested interface
+    //   Return: StatusCode indicating SUCCESS or FAILURE.
+    // N.B. Don't forget to release the interface after use!!!
+    virtual StatusCode queryInterface( const InterfaceID& riid, void** ppvInterface );
+
+    virtual StatusCode align        (IOVSVC_CALLBACK_ARGS);
+    virtual StatusCode compareTags  (IOVSVC_CALLBACK_ARGS);
+
+    virtual const IGeoModelTool* getTool(std::string toolName) const;
+
+    virtual StatusCode clear();
+
+    friend class SvcFactory<GeoModelSvc>;
+
+    // Standard Constructor
+    GeoModelSvc(const std::string& name, ISvcLocator* svc);
+
+    // Standard Destructor
+    virtual ~GeoModelSvc();
+
+
+protected:
+
+    //     StatusCode append( IGeoModelTool* pddTool, 
+    // 		       std::vector<IGeoModelTool*>* theTools ); 
+    //     StatusCode decodeNames( StringArrayProperty& theNames, 
+    //        						std::vector<IGeoModelTool*>* theTools ); 
+	
+private:
+
+    ToolHandleArray< IGeoModelTool > m_detectorTools; // Detector Tools
+
+    ISvcLocator*        m_pSvcLocator;
+
+    ServiceHandle<IToolSvc>     m_toolSvc;     
+    ServiceHandle<StoreGateSvc> m_detStore;   
+    ServiceHandle<ITagInfoMgr>  m_tagInfoMgr;   
+    ServiceHandle<IGeoDbTagSvc> m_geoDbTagSvc;
+
+    std::string           m_FaserVersion;
+
+    std::string           m_ScintVersionOverride;
+    // std::string           m_SCT_VersionOverride;
+    // std::string           m_CaloVersionOverride;
+    // std::string           m_MagFieldVersionOverride;
+    // std::string           m_CavernInfraVersionOverride;
+
+    bool          m_printMaterials;               // Print the contents of the Material Manager at the end of geoInit
+    bool          m_callBackON;                   // Register callback for Detector Tools
+    bool          m_ignoreTagDifference;          // Keep going if TagInfo and property tags are different
+                                                  // when geometry configured manually 
+    bool          m_useTagInfo;                   // Flag for TagInfo usage
+    bool          m_useCaloAlign;                 // Flag for using alignments for Calo
+    bool          m_statisticsToFile;             // Flag for generating GeoModelStatistics file in the run directory
+
+    int           m_supportedGeometry;            // Supported geometry flag is set in jobOpt and is equal to major release version
+    bool          m_ignoreTagSupport;             // If true then don't check SUPPORT flag for ATLAS tag
+
+    const std::string & faserVersion()         const {return m_FaserVersion; }
+    const std::string & scintVersionOverride() const {return m_ScintVersionOverride ;}
+    // const std::string & SCT_VersionOverride()  const {return m_SCT_VersionOverride  ;}
+    // const std::string & muonVersionOverride()  const {return m_MuonVersionOverride  ;}
+    // const std::string & caloVersionOverride()  const {return m_CaloVersionOverride  ;}
+    // const std::string & magFieldVersionOverride()     const {return m_MagFieldVersionOverride  ;}
+    // const std::string & cavernInfraVersionOverride()  const {return m_CavernInfraVersionOverride  ;}
+
+    const std::string & scintVersion()         const {return m_geoDbTagSvc->scintVersion(); }
+    // const std::string & SCT_Version()          const {return m_geoDbTagSvc->SCT_Version(); }
+    // const std::string & caloVersion()          const {return m_geoDbTagSvc->caloVersion(); }
+    // const std::string & magFieldVersion()      const {return m_geoDbTagSvc->magFieldVersion(); }
+    // const std::string & cavernInfraVersion()   const {return m_geoDbTagSvc->cavernInfraVersion(); }
+
+    GeoModel::GeoConfig geoConfig() const {return m_geoDbTagSvc->geoConfig();}
+
+    StatusCode geoInit ();
+    StatusCode fillTagInfo() const;
+};
+
+#endif // GEOMODELSVC_GEOMODELSVC_H
diff --git a/DetectorDescription/GeoModel/GeoModelSvc/src/RDBMaterialManager.cxx b/DetectorDescription/GeoModel/GeoModelSvc/src/RDBMaterialManager.cxx
new file mode 100644
index 000000000..23386d107
--- /dev/null
+++ b/DetectorDescription/GeoModel/GeoModelSvc/src/RDBMaterialManager.cxx
@@ -0,0 +1,961 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "RDBMaterialManager.h"
+#include "GeoModelUtilities/DecodeVersionKey.h"
+#include "GeoModelInterfaces/IGeoModelSvc.h"
+
+#include "GeoModelKernel/GeoMaterial.h"
+#include "GeoModelKernel/GeoElement.h"
+#include "GeoModelKernel/Units.h"
+
+#include "StoreGate/StoreGate.h"
+#include "StoreGate/DataHandle.h"
+
+#include "RDBAccessSvc/IRDBAccessSvc.h"
+#include "RDBAccessSvc/IRDBRecordset.h"
+#include "RDBAccessSvc/IRDBRecord.h"
+
+#include "AthenaKernel/getMessageSvc.h"
+#include "GaudiKernel/IMessageSvc.h"
+#include "GaudiKernel/ISvcLocator.h"
+#include "GaudiKernel/MsgStream.h"
+#include "GaudiKernel/SystemOfUnits.h"
+#include "AthenaBaseComps/AthCheckMacros.h"
+
+#include <algorithm>
+#include <iostream>
+#include <stdexcept>
+
+bool RDBMaterialManager::s_specialMaterials = false;
+
+//---------------------------Help find elements in the list-----------------------//
+class NameEquals {                                                                //
+public:                                                                           //
+  NameEquals(const std::string & name):m_name(name){}                              //
+  bool operator() (const GeoElement *e) const {return m_name==e->getName();}       //
+private:                                                                          //
+  std::string m_name;                                                              //
+};                                                                                //
+//--------------------------------------------------------------------------------//
+
+//---------------------------Help find elements in the list-----------------------//
+class NumberEquals {                                                              //
+public:                                                                           //
+  NumberEquals(unsigned int number):m_number(number){}                             //
+  bool operator() (const GeoElement *e) const {return m_number==e->getZ();}        //
+private:                                                                          //
+  unsigned int m_number;                                                           //
+};                                                                                //
+//--------------------------------------------------------------------------------//
+
+int CheckElement(std::string &name)
+{
+  if(name.find("::",0) == std::string::npos) {
+    return 1;
+  }
+  else {
+    return 0;	
+  }
+}
+
+int printElement ( GeoElement* &p_element)
+{
+  std::string name = p_element->getName();
+  std::string symbol = p_element->getSymbol();
+  double a = p_element->getA();
+  double z = p_element->getZ();
+	
+  std::cout << " ***** CheckElement(): Print the Element:  " << name << std::endl; 
+  std::cout << " ***** The Element: name,		symbol, 	A, 	Z " << std::endl; 
+  std::cout << " *****             "<<name <<"		"<<symbol <<"		"<< a * (Gaudi::Units::mole / GeoModelKernelUnits::gram) <<"	"<< z <<"	"  << std::endl;
+	
+  return 1;
+}
+
+int printElement ( const GeoElement* &p_element)
+{
+  std::string name = p_element->getName();
+  std::string symbol = p_element->getSymbol();
+  double a = p_element->getA();
+  double z = p_element->getZ();
+	
+  std::cout << " ***** PrintElement(): Print the Element:  " << name << std::endl; 
+  std::cout << " ***** The Element: name,		symbol, 	A, 	Z " << std::endl; 
+  std::cout << " *****             "<<name <<"		"<<symbol <<"		"<< a * (Gaudi::Units::mole / GeoModelKernelUnits::gram) <<"	"<< z <<"	"  << std::endl;
+	
+  return 1;
+}
+
+int printMaterial ( GeoMaterial* &p_material)
+{
+  std::string name = p_material->getName();
+  double density = p_material->getDensity() * (Gaudi::Units::cm3 / GeoModelKernelUnits::gram);
+
+  std::cout << " ***** PrintMaterial(): Print the Material:  " << name << std::endl; 
+  std::cout << " ***** The Material: name,	density	" << std::endl; 
+  std::cout << " *****              "<< name <<"		"<<density <<"		" << std::endl; 	
+	
+  return 1;
+}
+
+int printFullMaterial ( GeoMaterial* &p_material)
+{
+  std::string name = p_material->getName();
+  double density = p_material->getDensity() * (Gaudi::Units::cm3 / GeoModelKernelUnits::gram);
+	
+  std::cout << " ***** PrintFullMaterial(): Print the Material:  " << name << std::endl; 
+  std::cout << " ***** The Material: name, 	density" << std::endl; 
+  std::cout << " *****              "<< name <<" 	 "<<density <<"  " << std::endl; 
+	
+  p_material->lock();
+  int element_number = p_material->getNumElements();	
+		
+ 			
+  if ( element_number  == 0){
+    std::cout << " ***** No Elements now in this printMaterial( ) " << std::endl;	
+    return 1;
+  }
+  else {
+    element_number = p_material->getNumElements();	
+	
+    for(int i =0; i< element_number;i ++)
+      {
+	const GeoElement* tmp_element = p_material->getElement(i);
+	double element_fraction = p_material->getFraction(i);
+		
+	std::cout<<" ***** ***** Number:  " << i << " Fraction:  " << element_fraction<< std::endl;
+	printElement( tmp_element); 
+      }	
+  }
+  return 1;
+}
+	
+	
+
+RDBMaterialManager::RDBMaterialManager(ISvcLocator* pSvcLocator)
+{
+  if(!readMaterialsFromDB(pSvcLocator).isSuccess()) {
+    throw std::runtime_error("RDBMaterialManager failed to read Geometry DB");
+  }
+}
+
+StatusCode RDBMaterialManager::readMaterialsFromDB(ISvcLocator* pSvcLocator)
+{
+  IGeoModelSvc*  iGeoModel;		
+  IRDBAccessSvc* iAccessSvc;
+  MsgStream log(Athena::getMessageSvc(), "GeoModelSvc::RDBMaterialManager"); 		
+
+  ATH_CHECK(pSvcLocator->service("GeoModelSvc",iGeoModel));
+  ATH_CHECK(pSvcLocator->service("RDBAccessSvc",iAccessSvc));
+
+  // --- Standard materials, elements
+  DecodeVersionKey keyFaser(iGeoModel, "FASER");
+  m_elements = iAccessSvc->getRecordsetPtr("Elements",keyFaser.tag(),keyFaser.node());
+  if(m_elements->size()==0) {
+    if(log.level()<=MSG::WARNING)
+      log << MSG::WARNING << " Getting Elements with default tag" <<endmsg;
+    m_elements = iAccessSvc->getRecordsetPtr("Elements","Materials-00","Materials");
+  }
+  m_stdmatcomponents = iAccessSvc->getRecordsetPtr("StdMatComponents",keyFaser.tag(),keyFaser.node());
+  if(m_stdmatcomponents->size()==0)	{
+    if(log.level()<=MSG::WARNING)
+      log << MSG::WARNING << " Getting StdMatComponents with default tag" <<endmsg;
+    m_stdmatcomponents = iAccessSvc->getRecordsetPtr("StdMatComponents","Materials-00","Materials");
+  }
+  m_stdmaterials = iAccessSvc->getRecordsetPtr("StdMaterials",keyFaser.tag(),keyFaser.node());
+  if(m_stdmaterials->size()==0) {
+    if(log.level()<=MSG::WARNING)
+      log << MSG::WARNING << " Getting StdMaterials with default tag" <<endmsg;
+    m_stdmaterials = iAccessSvc->getRecordsetPtr("StdMaterials","Materials-00","Materials");
+  }
+  
+  // --- Pixel materials
+  DecodeVersionKey keyScintillator(iGeoModel, "Scintillator");
+  m_scintmatcomponents = iAccessSvc->getRecordsetPtr("ScintMatComponents",keyScintillator.tag(),keyScintillator.node());
+  if(m_scintmatcomponents->size()==0) {
+    if(log.level()<=MSG::WARNING)
+      log << MSG::WARNING << " Getting ScintMatComponents with default tag" <<endmsg;
+    m_scintmatcomponents = iAccessSvc->getRecordsetPtr("ScintMatComponents","ScintMatComponents-00");
+  }
+  m_scintmaterials = iAccessSvc->getRecordsetPtr("PixMaterials",keyScintillator.tag(),keyScintillator.node());
+  if(m_scintmaterials->size()==0) {
+    if(log.level()<=MSG::WARNING)
+      log << MSG::WARNING << " Getting ScintMaterials with default tag" <<endmsg;
+    m_scintmaterials = iAccessSvc->getRecordsetPtr("ScintMaterials","ScintMaterials-00");
+  }
+  
+  // --- SCT materials
+  // DecodeVersionKey keySCT(iGeoModel, "SCT");
+  // m_sctmatcomponents = iAccessSvc->getRecordsetPtr("SCTMatComponents",keySCT.tag(),keySCT.node());
+  // if(m_sctmatcomponents->size()==0)	{
+  //   if(log.level()<=MSG::WARNING)
+  //     log << MSG::WARNING << " Getting SCTMatComponents with default tag" <<endmsg;
+  //   m_sctmatcomponents = iAccessSvc->getRecordsetPtr("SCTMatComponents","SCTMatComponents-00");
+  // }
+  
+  // m_sctmaterials = iAccessSvc->getRecordsetPtr("SCTMaterials",keySCT.tag(),keySCT.node());
+  // if(m_sctmaterials->size()==0) {
+  //   if(log.level()<=MSG::WARNING)
+  //     log << MSG::WARNING << " Getting SCTMaterials with default tag" <<endmsg;
+  //   m_sctmaterials = iAccessSvc->getRecordsetPtr("SCTMaterials","SCTMaterials-00");
+  // }
+   
+  // --- InDet common materials
+  // DecodeVersionKey keyInDet(iGeoModel, "InnerDetector");
+  // m_indetmatcomponents = iAccessSvc->getRecordsetPtr("InDetMatComponents",keyInDet.tag(),keyInDet.node());
+  // if(m_indetmatcomponents->size()==0) {
+  //   if(log.level()<=MSG::WARNING)
+  //     log << MSG::WARNING << " Getting InDetMatComponents with default tag" <<endmsg;
+  //   m_indetmatcomponents = iAccessSvc->getRecordsetPtr("InDetMatComponents","InDetMatComponents-00");
+  // }
+  
+  // m_indetmaterials = iAccessSvc->getRecordsetPtr("InDetMaterials",keyInDet.tag(),keyInDet.node());
+  // if(m_indetmaterials->size()==0) {
+  //   if(log.level()<=MSG::WARNING)
+  //     log << MSG::WARNING << " Getting InDetMaterials with default tag" <<endmsg;
+  //   m_indetmaterials = iAccessSvc->getRecordsetPtr("InDetMaterials","InDetMaterials-00");
+  // }
+  
+  return StatusCode::SUCCESS;
+}
+
+// Destructor:
+RDBMaterialManager::~RDBMaterialManager() {
+	
+  // Unreference the materials:
+  std::map< std::string, GeoMaterial * >::iterator m, begin = m_materialMap.begin(),end = m_materialMap.end();
+  for (m=begin;m!=end;m++) (*m).second->unref();	
+	 	
+  // Unreference the elements:
+  for (size_t i=0;i<m_elementVector.size();i++)   	m_elementVector[i]->unref();
+	
+}
+
+GeoMaterial* RDBMaterialManager::searchMaterialMap(const std::string & name)  
+{
+  MsgStream log(Athena::getMessageSvc(), "GeoModelSvc::RDBMaterialManager"); 
+	
+  std::map< std::string, GeoMaterial * >::const_iterator m   = m_materialMap.find(std::string(name));
+  std::map< std::string, GeoMaterial * >::const_iterator end = m_materialMap.end();
+  	
+  if (m!=end) {
+    if(log.level()==MSG::VERBOSE)
+      log << MSG::VERBOSE << " ***** in searchMaterialMap(): search sucess "  << endmsg;	
+    return (*m).second;
+  }
+  else {
+    if(log.level()==MSG::VERBOSE)
+      log << MSG::VERBOSE << " ***** in searchMaterialMap(): search fail "  << endmsg;	
+    return NULL;
+  }
+}
+
+GeoMaterial* RDBMaterialManager::searchMaterialMap(const std::string & name) const
+{
+  MsgStream log(Athena::getMessageSvc(), "GeoModelSvc::RDBMaterialManager"); 
+	
+  std::map< std::string, GeoMaterial * >::const_iterator m   = m_materialMap.find(std::string(name));
+  std::map< std::string, GeoMaterial * >::const_iterator end = m_materialMap.end();
+  if (m!=end) {
+    if(log.level()==MSG::VERBOSE)
+      log << MSG::VERBOSE << " ***** in searchMaterialMap(): search sucess "  << endmsg;	
+    return (*m).second;
+  }
+  else {
+    if(log.level()==MSG::VERBOSE)
+      log << MSG::VERBOSE << " ***** in searchMaterialMap(): search fail "  << endmsg;	
+    return NULL;
+  }
+}
+
+
+GeoElement *RDBMaterialManager::searchElementVector(const std::string & name)  
+{ 
+  MsgStream log(Athena::getMessageSvc(), "GeoModelSvc::RDBMaterialManager"); 
+	
+  NameEquals matchByName(name);
+  std::vector<GeoElement *>::const_iterator e=std::find_if(m_elementVector.begin(), m_elementVector.end(),matchByName);
+  	
+  if (e!=m_elementVector.end()) {	
+    if(log.level()==MSG::VERBOSE)
+      log << MSG::VERBOSE << " ***** in searchElementVector() search succes "  << endmsg;	
+    return *e;
+  }
+  else {
+    if(log.level()==MSG::VERBOSE)
+      log << MSG::VERBOSE << " ***** in searchElementVector() search fail "  << endmsg;	
+    return NULL;
+  }
+}
+
+
+GeoElement *RDBMaterialManager::searchElementVector(const std::string & name)  const
+{ 
+  MsgStream log(Athena::getMessageSvc(), "GeoModelSvc::RDBMaterialManager"); 
+	
+  NameEquals matchByName(name);
+  std::vector<GeoElement *>::const_iterator e=std::find_if(m_elementVector.begin(), m_elementVector.end(),matchByName);
+  	
+  if (e!=m_elementVector.end()) {	
+    if(log.level()==MSG::VERBOSE)    		
+      log << MSG::VERBOSE << " ***** in searchElementVector() search succes "  << endmsg;	
+    return *e;
+  }
+  else {
+    if(log.level()==MSG::VERBOSE)
+      log << MSG::VERBOSE << " ***** in searchElementVector() search fail "  << endmsg;	
+    return NULL;
+  }
+}
+
+
+GeoElement *RDBMaterialManager::searchElementVector(const unsigned int atomicNumber)  
+{ 
+  MsgStream log(Athena::getMessageSvc(), "GeoModelSvc::RDBMaterialManager"); 
+	
+  NumberEquals matchByNumber(atomicNumber);
+  std::vector<GeoElement *>::const_iterator e=std::find_if(m_elementVector.begin(), m_elementVector.end(), matchByNumber);
+  	
+  if (e!=m_elementVector.end()) {
+    if(log.level()==MSG::VERBOSE)  		
+      log << MSG::VERBOSE << " ***** in searchElementVector(atomicNumber) search succes "  << endmsg;
+    return *e;
+  }
+  else {
+    if(log.level()==MSG::VERBOSE)
+      log << MSG::VERBOSE << " ***** in searchElementVector(atomicNumber) search succes "  << endmsg;
+    return NULL;
+  }
+}
+
+GeoElement *RDBMaterialManager::searchElementVector(const unsigned int atomicNumber) const
+{ 
+  MsgStream log(Athena::getMessageSvc(), "GeoModelSvc::RDBMaterialManager"); 
+	
+  NumberEquals matchByNumber(atomicNumber);
+  std::vector<GeoElement *>::const_iterator e=std::find_if(m_elementVector.begin(), m_elementVector.end(), matchByNumber);
+  	
+  if (e!=m_elementVector.end()) {
+    if(log.level()==MSG::VERBOSE)  		
+      log << MSG::VERBOSE << " ***** in searchElementVector(atomicNumber) search succes "  << endmsg;
+    return *e;
+  }
+  else {
+    if(log.level()==MSG::VERBOSE)
+      log << MSG::VERBOSE << " ***** in searchElementVector(atomicNumber) search succes "  << endmsg;
+    return NULL;
+  }
+}
+
+GeoMaterial* RDBMaterialManager::getMaterial(const std::string & name) {
+	
+  unsigned int  ind, com_ind;
+	
+  std::string material_name;
+  std::string tmp_name;
+  long 	    material_id = 0;
+  double      material_density = 0;
+	
+	
+  std::string component_name;
+  double      component_fraction;
+  int 	    component_id;
+		
+  std::string detector;
+  std::string tmp_det;
+  std::string data_id;
+	
+	
+  std::string matcomponents_table;
+
+  if(!s_specialMaterials)
+  {
+    buildSpecialMaterials();
+    s_specialMaterials = true;
+  }
+	
+  GeoMaterial* pmaterial;
+	
+  GeoMaterial* p_com_material;
+  GeoElement*  p_com_element;
+	
+  IRDBRecordset_ptr tmp_materials;
+  IRDBRecordset_ptr tmp_matcomponents;
+	
+  MsgStream log(Athena::getMessageSvc(), "GeoModelSvc::RDBMaterialManager"); 
+  if(log.level()<=MSG::DEBUG) 
+    log << MSG::DEBUG  << " ***** getMaterial( ): "  << name << endmsg;	
+ 
+
+  pmaterial = NULL;
+  pmaterial = searchMaterialMap( name);
+  if (pmaterial!= NULL) 
+      return pmaterial;
+		
+  if(name.find("std",0) == 0)
+    {
+      detector = "std";
+      tmp_materials = m_stdmaterials;
+      tmp_matcomponents = m_stdmatcomponents;
+      data_id = "STDMATERIALS_DATA_ID";
+    }
+  else if(name.find("scint",0) == 0)
+    {
+      detector = "scint";
+      tmp_materials = m_scintmaterials;
+      tmp_matcomponents = m_scintmatcomponents;
+      data_id = "SCINTMATERIALS_DATA_ID";
+    }
+  // else if(name.find("sct",0) == 0)
+  //   {
+  //     detector = "sct";
+  //     tmp_materials = m_sctmaterials;
+  //     tmp_matcomponents = m_sctmatcomponents;
+  //     data_id = "SCTMATERIALS_DATA_ID";
+  //   }
+  // else if(name.find("indet",0) == 0)
+  //   {
+  //     detector = "indet";
+  //     tmp_materials = m_indetmaterials;
+  //     tmp_matcomponents = m_indetmatcomponents;
+  //     data_id = "INDETMATERIALS_DATA_ID";
+  //   }
+  else {return 0 ;}
+	
+  for( ind = 0; ind < tmp_materials->size(); ind++)
+    {
+      const IRDBRecord* rec = (*tmp_materials)[ind];
+      tmp_name = detector+"::"+rec->getString("NAME");
+		
+      if( name == tmp_name){
+
+	material_name  = rec->getString("NAME");
+	material_id = rec->getLong(data_id);
+	material_density = rec->getDouble("DENSITY");
+        		
+	if(log.level()<=MSG::DEBUG)
+	  log << MSG::DEBUG  << " ***** Material: name id density: "  << material_name <<" " << material_id <<" "<< material_density << endmsg;	
+	break;
+      }
+    }
+		
+  if (ind == tmp_materials->size()) 
+      return NULL;
+
+  pmaterial = new GeoMaterial( material_name,material_density * (GeoModelKernelUnits::gram / Gaudi::Units::cm3));
+
+
+  bool firstComponent = true;
+  bool hasSubMaterial = false;
+  bool calculateFraction = false;
+  double totalFraction = 0.;
+  std::vector < GeoElement* > elementComponents;
+  std::vector <double>        elementFractions;
+
+  for(  com_ind = 0; com_ind <tmp_matcomponents->size(); com_ind++)
+    {
+      const IRDBRecord* com_rec = (*tmp_matcomponents)[com_ind];
+		
+      component_id = com_rec->getLong("MATERIAL_ID");
+      if( component_id == material_id)
+	{
+	  component_name = com_rec->getString("COMPNAME");
+	  component_fraction = com_rec->getDouble("FRACTION");
+			
+	  if(firstComponent)
+	  {
+	    firstComponent = false;
+	    if(component_fraction>=1.)
+	      calculateFraction = true;
+	  }
+
+	  if( CheckElement( component_name) == 1)
+	    {
+	      p_com_element = getElement(component_name);
+
+	      if(calculateFraction)
+	      {
+          totalFraction += component_fraction*p_com_element->getA();
+          elementComponents.push_back(p_com_element);
+          elementFractions.push_back(component_fraction);
+	      }
+	      else
+          pmaterial->add( p_com_element, component_fraction);
+										
+	    }
+	  else{
+	    hasSubMaterial = true;
+	    p_com_material = getMaterial(component_name);
+
+	    pmaterial->add(p_com_material, component_fraction);
+			
+	  }		
+	}
+    }    
+
+  if(calculateFraction && hasSubMaterial && elementComponents.size()>0)
+    std::cerr << material_name << " description should be changed. Please indicate the exact fraction for elements\n";
+
+  if(calculateFraction && !elementComponents.empty()) {
+    const double inv_totalFraction = 1. / totalFraction;
+    for(unsigned i=0; i<elementComponents.size(); i++)
+      pmaterial->add(elementComponents[i],elementFractions[i]*elementComponents[i]->getA() * inv_totalFraction);
+  }
+	
+  // a table to keep the memory allocation, and easy for delete 
+  addMaterial(detector,pmaterial);
+	
+  /*	{
+	printFullMaterial ( pmaterial);
+	printAll( std:: cout);
+	}
+  */	
+  return pmaterial;
+}
+
+const GeoMaterial*  RDBMaterialManager:: getMaterial(const std::string &name) const{
+
+  unsigned int  ind, com_ind;
+	
+  std::string material_name;
+  std::string tmp_name;
+  long 	    material_id = 0;
+  double      material_density = 0;
+	
+	
+  std::string component_name;
+  double      component_fraction;
+  int 	    component_id;
+		
+  std::string detector;
+  std::string tmp_det;
+  std::string data_id;
+	
+	
+  std::string matcomponents_table;
+
+  if(!s_specialMaterials)
+  {
+    buildSpecialMaterials();
+    s_specialMaterials = true;
+  }
+
+	
+  GeoMaterial* pmaterial;
+	
+  GeoMaterial* p_com_material;
+  GeoElement*  p_com_element;
+	
+  IRDBRecordset_ptr tmp_materials;
+  IRDBRecordset_ptr tmp_matcomponents;
+	
+  MsgStream log(Athena::getMessageSvc(), "GeoModelSvc::RDBMaterialManager"); 
+  if(log.level()<=MSG::DEBUG) 
+    log << MSG::DEBUG  << " ***** getMaterial( ): "  << name << endmsg;	
+
+  pmaterial = NULL;
+  pmaterial = searchMaterialMap( name);
+  if (pmaterial!= NULL) 
+      return pmaterial;
+		
+  if(name.find("std",0) == 0)
+    {
+      detector = "std";
+      tmp_materials = m_stdmaterials;
+      tmp_matcomponents = m_stdmatcomponents;
+      data_id = "STDMATERIALS_DATA_ID";
+    }
+  else if(name.find("scint",0) == 0)
+    {
+      detector = "scint";
+      tmp_materials = m_scintmaterials;
+      tmp_matcomponents = m_scintmatcomponents;
+      data_id = "SCINTMATERIALS_DATA_ID";
+    }
+  // else if(name.find("sct",0) == 0)
+  //   {
+  //     detector = "sct";
+  //     tmp_materials = m_sctmaterials;
+  //     tmp_matcomponents = m_sctmatcomponents;
+  //     data_id = "SCTMATERIALS_DATA_ID";
+  //   }
+  // else if(name.find("indet",0) == 0)
+  //   {
+  //     detector = "indet";
+  //     tmp_materials = m_indetmaterials;
+  //     tmp_matcomponents = m_indetmatcomponents;
+  //     data_id = "INDETMATERIALS_DATA_ID";
+  //   }
+  else {return 0 ;}
+	
+  for( ind = 0; ind < tmp_materials->size(); ind++)
+    {
+      const IRDBRecord* rec = (*tmp_materials)[ind];
+      tmp_name = detector+"::"+rec->getString("NAME");
+		
+      if( name == tmp_name){
+        material_name  = rec->getString("NAME");
+        material_id = rec->getLong(data_id);
+        material_density = rec->getDouble("DENSITY");
+        		
+        if(log.level()<=MSG::DEBUG)
+          log << MSG::DEBUG  << " ***** Material: name id density: "  << material_name <<" " << material_id <<" "<< material_density << endmsg;	
+        break;
+      }
+    }
+		
+  if (ind == tmp_materials->size()) 
+      return NULL;
+
+  pmaterial = new GeoMaterial( material_name,material_density * (GeoModelKernelUnits::gram / Gaudi::Units::cm3));
+
+  bool firstComponent = true;
+  bool hasSubMaterial = false;
+  bool calculateFraction = false;
+  double totalFraction = 0.;
+  std::vector < GeoElement* > elementComponents;
+  std::vector <double>        elementFractions;
+
+  for(  com_ind = 0; com_ind <tmp_matcomponents->size(); com_ind++)
+    {
+      const IRDBRecord* com_rec = (*tmp_matcomponents)[com_ind];
+		
+      component_id = com_rec->getLong("MATERIAL_ID");
+      if( component_id == material_id)
+	{
+	  component_name = com_rec->getString("COMPNAME");
+	  component_fraction = com_rec->getDouble("FRACTION");
+			
+	  if(firstComponent)
+	  {
+	    firstComponent = false;
+	    if(component_fraction>=1.)
+	      calculateFraction = true;
+	  }
+
+	  if( CheckElement( component_name) == 1)
+	    {
+	      p_com_element = (GeoElement *)(getElement(component_name));
+
+	      if(calculateFraction)
+	      {
+          totalFraction += component_fraction*p_com_element->getA();
+          elementComponents.push_back(p_com_element);
+          elementFractions.push_back(component_fraction);
+	      }
+	      else
+          pmaterial->add( p_com_element, component_fraction);
+										
+	    }
+	  else{
+	    hasSubMaterial = true;
+	    p_com_material = (GeoMaterial  *)getMaterial(component_name);
+
+	    pmaterial->add(p_com_material, component_fraction);
+			
+	  }		
+	}
+    }    
+
+  if(calculateFraction && hasSubMaterial && elementComponents.size()>0)
+    std::cerr << material_name << " description should be changed. Please indicate the exact fraction for elements\n";
+
+  if(calculateFraction && !elementComponents.empty()) {
+    double inv_totalFraction = 1. / totalFraction;
+    for(unsigned i=0; i<elementComponents.size(); i++)
+      pmaterial->add(elementComponents[i],elementFractions[i]*elementComponents[i]->getA() * inv_totalFraction);
+  }
+
+  // a table to keep the memory allocation, and easy for delete 
+  addMaterial(detector,pmaterial);
+	
+  return pmaterial;
+}
+
+
+const GeoElement *RDBMaterialManager::getElement(const std::string & name) const{
+	
+  unsigned int ind;
+
+  std::string element_name;
+  std::string element_symbol;
+  std::string tmp_name;
+	
+  double      element_a;
+  double      element_z;
+	
+  GeoElement *pelement;
+
+  pelement = NULL;
+  pelement = searchElementVector( name);
+  if (pelement != NULL) 
+      return pelement;
+
+  MsgStream log(Athena::getMessageSvc(), "GeoModelSvc::RDBMaterialManager"); 
+  if(log.level()==MSG::VERBOSE)
+    log << MSG::VERBOSE << " ***** getElement(): " << name  <<endmsg;
+
+  for(ind = 0; ind < m_elements->size(); ind++)
+    {
+      const IRDBRecord* rec = (*m_elements)[ind];
+		
+      tmp_name = rec->getString("NAME");
+	
+      if( name == tmp_name)
+      { 
+        element_name   = rec->getString("NAME");
+        element_symbol = rec->getString("SYMBOL");
+        element_a = rec->getDouble("A");
+        element_z = rec->getDouble("Z");
+                      
+        pelement = new GeoElement( element_name , element_symbol  ,element_z , element_a *(GeoModelKernelUnits::gram/Gaudi::Units::mole));
+
+        // a table to keep the memory allocation, and easy for delete 
+        pelement->ref();
+        m_elementVector.push_back( pelement);
+          
+        break;
+      }
+    }
+  if (ind == m_elements->size()) 		return NULL;
+	
+  return pelement;
+
+}
+
+
+const GeoElement *RDBMaterialManager::getElement(unsigned int atomicNumber) const {
+
+  unsigned int ind;
+
+  std::string element_name;
+  std::string element_symbol;
+	
+  double      element_a;
+  double      element_z;
+	
+  GeoElement* pelement(0);
+
+  MsgStream log(Athena::getMessageSvc(), "GeoModelSvc::RDBMaterialManager"); 
+  if(log.level()==MSG::VERBOSE)
+    log << MSG::VERBOSE << " ***** const getElement(atomicNumber) const : " << atomicNumber <<endmsg;	
+
+  for(ind = 0; ind < m_elements->size(); ind++)
+    {
+      const IRDBRecord* rec = (*m_elements)[ind];
+		
+      if(atomicNumber == rec->getDouble("A"))
+      { 
+        element_name   = rec->getString("NAME");
+        element_symbol = rec->getString("SYMBOL");
+        element_a = rec->getDouble("A");
+        element_z = rec->getDouble("Z");
+                      
+        pelement = new GeoElement( element_name , element_symbol  ,element_z , element_a *(GeoModelKernelUnits::gram/Gaudi::Units::mole));
+
+        // a table to keep the memory allocation, and easy for delete 
+        pelement->ref();
+        m_elementVector.push_back( pelement);
+          
+        break;
+      }
+    }
+  if (ind == m_elements->size()) 	return NULL;
+	
+  return pelement;
+}
+
+
+GeoElement *RDBMaterialManager::getElement(const std::string & name)  {
+
+  unsigned int ind;
+
+  std::string element_name;
+  std::string element_symbol;
+  std::string tmp_name;
+	
+  double      element_a;
+  double      element_z;
+	
+  GeoElement *pelement;
+
+  MsgStream log(Athena::getMessageSvc(), "GeoModelSvc::RDBMaterialManager"); 
+  if(log.level()==MSG::VERBOSE)
+    log << MSG::VERBOSE << " ***** getElement(): " << element_name  <<endmsg;
+	
+  pelement = NULL;
+  pelement = searchElementVector( name);
+  if (pelement != NULL) 
+      return pelement;
+
+  for(ind = 0; ind < m_elements->size(); ind++)
+    {
+      const IRDBRecord* rec = (*m_elements)[ind];
+		
+      tmp_name = rec->getString("NAME");
+	
+      if( name == tmp_name)
+      { 
+        element_name   = rec->getString("NAME");
+        element_symbol = rec->getString("SYMBOL");
+        element_a = rec->getDouble("A");
+        element_z = rec->getDouble("Z");
+                      
+        pelement = new GeoElement( element_name , element_symbol  ,element_z , element_a *(GeoModelKernelUnits::gram/Gaudi::Units::mole));
+
+        // a table to keep the memory allocation, and easy for delete 
+        pelement->ref();
+        m_elementVector.push_back( pelement);
+        break;
+          
+      }
+    }
+  if (ind == m_elements->size()) 		return NULL;
+	
+  return pelement;
+}
+
+
+GeoElement *RDBMaterialManager::getElement(unsigned int atomicNumber) {
+  
+  unsigned int ind;
+
+  std::string element_name;
+  std::string element_symbol;
+	
+  double      element_a;
+  double      element_z;
+	
+  GeoElement* pelement(0);
+
+  MsgStream log(Athena::getMessageSvc(), "GeoModelSvc::RDBMaterialManager"); 
+  if(log.level()==MSG::VERBOSE)
+    log << MSG::VERBOSE << " ***** getElement(atomicNumber): " << element_name  <<endmsg;	
+	
+  for(ind = 0; ind < m_elements->size(); ind++)
+    {
+      const IRDBRecord* rec = (*m_elements)[ind];
+		
+      if(atomicNumber == rec->getDouble("A"))
+      { 
+        element_name   = rec->getString("NAME");
+        element_symbol = rec->getString("SYMBOL");
+        element_a = rec->getDouble("A");
+        element_z = rec->getDouble("Z");
+                      
+        pelement = new GeoElement( element_name , element_symbol  ,element_z , element_a *(GeoModelKernelUnits::gram/Gaudi::Units::mole));
+
+        // a table to keep the memory allocation, and easy for delete 
+        pelement->ref();
+        m_elementVector.push_back( pelement);
+          
+        break;
+      }
+    }
+  if (ind == m_elements->size()) 	return NULL;
+	
+  return pelement;
+}
+
+void RDBMaterialManager::addMaterial(const std::string & space, GeoMaterial *material) {
+
+  MsgStream log(Athena::getMessageSvc(), "GeoModelSvc::RDBMaterialManager"); 
+  if(log.level()==MSG::VERBOSE)
+    log << MSG::VERBOSE << " ***** RDBMaterialManager::addMaterial() "<<endmsg;
+	
+  std::string key = space + std::string("::")+ std::string(material->getName());
+  // Check whether we already have materials with the same space::name defined
+  if(m_materialMap.find(key)!=m_materialMap.end())
+    log << MSG::WARNING << " Attempt to redefine material " << key << "!. The existing instance is kept. Please choose another name for new material" << endmsg;
+  else {
+    material->lock();             
+    material->ref();
+    m_materialMap[key]=material;
+  }
+}
+
+void RDBMaterialManager::addMaterial(const std::string & space, GeoMaterial *material) const {
+	
+  MsgStream log(Athena::getMessageSvc(), "GeoModelSvc::RDBMaterialManager"); 
+  if(log.level()==MSG::VERBOSE)
+    log << MSG::VERBOSE << " ***** RDBMaterialManager::addMaterial() "<<endmsg;
+	
+  std::string key = space + std::string("::")+ std::string(material->getName());
+  // Check whether we already have materials with the same space::name defined
+  if(m_materialMap.find(key)!=m_materialMap.end())
+    log << MSG::WARNING << " Attempt to redefine material " << key << "!. The existing instance is kept. Please choose another name for new material" << endmsg;
+  else {
+    material->lock();             
+    material->ref();
+    m_materialMap[key]=material;
+  }
+}
+
+StoredMaterialManager::MaterialMapIterator RDBMaterialManager::begin() const
+{
+  return m_materialMap.begin();
+}
+
+StoredMaterialManager::MaterialMapIterator RDBMaterialManager::end() const
+{
+  return m_materialMap.end();
+}
+
+size_t RDBMaterialManager::size()
+{
+  return m_materialMap.size();
+}
+
+std::ostream &  RDBMaterialManager::printAll(std::ostream & o) const 
+{
+  o << "============Material Manager Element List========================" << std::endl;
+  std::vector<GeoElement *>::const_iterator e;
+  for (e=m_elementVector.begin();e!= m_elementVector.end();e++) 
+    {
+      o << (*e)->getSymbol() << '\t' << (*e)->getZ() <<  '\t' << (*e)->getA() * (Gaudi::Units::mole / GeoModelKernelUnits::gram) << '\t' << (*e)->getName() << std::endl;
+    }
+  std::map<std::string, GeoMaterial *>::const_iterator m;
+  	
+  for (m=m_materialMap.begin();m!=m_materialMap.end();m++) 
+    {
+      o << "Material: " << (*m).first <<  " Density " << (*m).second->getDensity() * (Gaudi::Units::cm3 / GeoModelKernelUnits::gram)  << std::endl;
+      for (size_t i = 0; i< (*m).second->getNumElements();i++) 
+	{
+	  o <<" ***** ***** "<< int ((*m).second->getFraction(i)*100) << "% \t"  << (*m).second->getElement(i)->getName() << std::endl;
+	}
+    }
+  	  	
+  return o;
+}
+
+void RDBMaterialManager::buildSpecialMaterials()
+{
+  // Create special materials
+  GeoElement* ethElement = new GeoElement("Ether","ET",500.0,0.0);
+  ethElement->ref();
+  m_elementVector.push_back(ethElement);
+  GeoMaterial* ether = new GeoMaterial("Ether",0.0);	
+  ether->add(ethElement,1.);
+  addMaterial("special",ether);
+  // "Alternative" assembly material
+  GeoMaterial* hu = new GeoMaterial("HyperUranium",0.0);	
+  hu->add(ethElement,1.);
+  addMaterial("special",hu);
+}
+
+void RDBMaterialManager::buildSpecialMaterials() const
+{
+  // Create special materials
+  GeoElement* ethElement = new GeoElement("Ether","ET",500.0,0.0);
+  ethElement->ref();
+  m_elementVector.push_back(ethElement);  
+  GeoMaterial* ether = new GeoMaterial("Ether",0.0);	
+  ether->add(ethElement,1.);
+  addMaterial("special",ether);
+  // "Alternative" assembly material
+  GeoMaterial* hu = new GeoMaterial("HyperUranium",0.0);	
+  hu->add(ethElement,1.);
+  addMaterial("special",hu);
+}
diff --git a/DetectorDescription/GeoModel/GeoModelSvc/src/RDBMaterialManager.h b/DetectorDescription/GeoModel/GeoModelSvc/src/RDBMaterialManager.h
new file mode 100644
index 000000000..d0904e16b
--- /dev/null
+++ b/DetectorDescription/GeoModel/GeoModelSvc/src/RDBMaterialManager.h
@@ -0,0 +1,94 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef _RDBMATERIALMANAGER_H_
+#define _RDBMATERIALMANAGER_H_
+//---------------------------------------------------------//
+//                                                         //
+// class RDBMaterialManager  This is a material manager   //
+// which gets its material from RDB.                       //
+//                                                         //
+// Joe Boudreau March 2003                                 //
+//                                                         //
+// Heavily modified for FASER                              //
+//                                                         //
+//---------------------------------------------------------//
+#include "GeoModelInterfaces/StoredMaterialManager.h"
+#include "RDBAccessSvc/IRDBAccessSvc.h"
+
+#include <string>
+#include <map>
+#include <vector>
+#include <iosfwd>
+
+class GeoMaterial;
+class ISvcLocator;
+
+
+class RDBMaterialManager: public StoredMaterialManager {
+
+ public:
+
+  // Constructor:
+  RDBMaterialManager(ISvcLocator* pSvcLocator);
+  
+  // Destructor:
+  virtual ~RDBMaterialManager();
+
+  // Query the material:
+  virtual       GeoMaterial *getMaterial(const std::string &name) ;
+  virtual const GeoMaterial *getMaterial(const std::string &name) const;
+ 
+
+  // Query the elements:
+  virtual const GeoElement *getElement(const std::string & name) const;
+  virtual       GeoElement *getElement(const std::string & name);
+
+  // Query the elements (by atomic number):
+  virtual const GeoElement *getElement(unsigned int atomicNumber) const;
+  virtual       GeoElement *getElement(unsigned int atomicNumber);
+
+  // Add new material
+  virtual void addMaterial(const std::string& space, GeoMaterial* material);
+  virtual void addMaterial(const std::string& space, GeoMaterial* material) const;
+
+  virtual StoredMaterialManager::MaterialMapIterator begin() const;
+  virtual StoredMaterialManager::MaterialMapIterator end() const;
+
+  // Number of materials in the manager
+  virtual size_t size();
+
+  virtual std::ostream & printAll(std::ostream & o=std::cout) const;
+
+ private:
+  static bool s_specialMaterials;
+
+  StatusCode readMaterialsFromDB(ISvcLocator* pSvcLocator);
+
+  void buildSpecialMaterials();
+  void buildSpecialMaterials() const;
+
+  GeoElement *searchElementVector (const std::string & name);
+  GeoElement *searchElementVector (const std::string & name) const;
+  
+  GeoElement *searchElementVector (const unsigned int atomicNumber);
+  GeoElement *searchElementVector (const unsigned int atomicNumber) const;
+  
+  GeoMaterial *searchMaterialMap (const std::string & name);
+  GeoMaterial *searchMaterialMap (const std::string & name) const;
+  
+  // For DataBase connection and Query
+  IRDBRecordset_ptr m_elements;
+  
+  IRDBRecordset_ptr m_stdmaterials;
+  IRDBRecordset_ptr m_stdmatcomponents;
+  IRDBRecordset_ptr m_scintmaterials;
+  IRDBRecordset_ptr m_scintmatcomponents;
+
+  mutable std::vector < GeoElement *>        m_elementVector;
+  mutable StoredMaterialManager::MaterialMap m_materialMap;
+};
+
+
+#endif
diff --git a/DetectorDescription/GeoModel/GeoModelSvc/src/components/GeoModelSvc_entries.cxx b/DetectorDescription/GeoModel/GeoModelSvc/src/components/GeoModelSvc_entries.cxx
new file mode 100644
index 000000000..eda713dbf
--- /dev/null
+++ b/DetectorDescription/GeoModel/GeoModelSvc/src/components/GeoModelSvc_entries.cxx
@@ -0,0 +1,6 @@
+#include "../GeoModelSvc.h"
+#include "../GeoDbTagSvc.h"
+
+DECLARE_COMPONENT( GeoModelSvc )
+DECLARE_COMPONENT( GeoDbTagSvc )
+
-- 
GitLab