diff --git a/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/GeoDeDuplicator.h b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/GeoDeDuplicator.h
new file mode 100644
index 0000000000000000000000000000000000000000..b11634c8c25da825806fc5f0c2d5f5f2caba4e04
--- /dev/null
+++ b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/GeoDeDuplicator.h
@@ -0,0 +1,94 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+#ifndef GEOMODELFUNCSNIPPETS_GEODEDUPLICATOR_H
+#define GEOMODELFUNCSNIPPETS_GEODEDUPLICATOR_H
+
+#include "GeoModelKernel/GeoPhysVol.h"
+#include "GeoModelKernel/GeoShape.h"
+#include "GeoModelKernel/GeoTransform.h"
+
+#include "GeoModelFuncSnippets/GeoLogVolSorter.h"
+#include "GeoModelFuncSnippets/GeoPhysVolSorter.h"
+#include "GeoModelFuncSnippets/GeoShapeSorter.h"
+#include "GeoModelFuncSnippets/TransformSorter.h"
+
+#include <set>
+/***
+ *  Helper class to deduplicate shapes, volumes and non-alignable transforms in the GeoModel tree that are equivalent
+ *  but instantiated in different places. Every time when the cache function is invoked, it's tried to insert the object 
+ *  into its respective store. If another object which is equivalent in terms of the GeoLogVolSorter, GeoPhysVolSorter or 
+ *  GeoTransformSorter has been already added, the parsed object is deleted and the pointer to the already cached one is returned
+ * 
+ * 
+ *  Usage for GeoTransforms:
+ * 
+ *  Instead of
+ *        GeoTransform* xtrf = new GeoTransform(<Some transform to the volume> );
+ * 
+ *  just do
+ *        GeoTransform* xtrf = makeTransform(<Some transform to the volume> );
+ * 
+ *  NOTE: GeoTransforms are shared across all instances of the GeoDeDuplicator class
+ * 
+ *  Useage for GeoShapes:
+ *      Perform the usual assembly of the shape e.g.
+ *       
+ *          GeoShape* tube = new GeoTube(10,42, 66);
+ *
+ *     If you combine the GeoShape with the logical volume then do
+ * 
+ *           GeoLogVol* logVol = new GeoLogVol("TheCakeTastes", cacheShape(tube), cakeMaterial);
+ *      
+ *      In a similar fashion repeating components of GeoShapes in Boolean shapes can be made shared as well
+ * 
+ *  NOTE: GeoShapes are shares across all instances of the GeoDeuplicator class
+ * 
+ *   Useage for GeoFullPhysVol:
+ *          GeoFullPhysVol are never shared and can neither be added to the GeoDeDuplicator. However, it's possible 
+ *          to share the same logical volume across several physical volumes
+ *        
+ *      GeoFullPhysVol* fullPhyVol = new GeoFullPhyVol(cacheVolume(logVol));
+ * 
+ *   Useage for ordinary GeoPhysVol:
+ * 
+ *        Assemble the GeoPhysVol as it's needed
+ *        
+ *        GeoPhysVol* subVol = new GeoPhysVol(cacheVolume(logVol2));
+ *        GeoPhysVol* subVol1 = new GeoPhysVol(cacheVolume(logVol3));
+ *        
+ *        subVol->add(makeTransform(GeoTrf::TranslateX3D(999)));
+ *        subVol->add(cacheVolume(subVol1));
+ * 
+ *        fullPhysVol->add(cacheVolume(subVol));
+ * 
+*/
+class GeoDeDuplicator {
+    public:
+        using GeoShapePtr = GeoIntrusivePtr<const GeoShape>;
+        using GeoLogVolPtr = GeoIntrusivePtr<GeoLogVol>;
+        using GeoTrfPtr =  GeoIntrusivePtr<GeoTransform>;
+        using GeoPhysVolPtr = GeoIntrusivePtr<GeoPhysVol>;
+
+        GeoDeDuplicator() = default;
+        ~GeoDeDuplicator() = default;
+
+        GeoPhysVolPtr cacheVolume(GeoPhysVolPtr vol) const;
+        GeoTrfPtr makeTransform(const GeoTrf::Transform3D& trf) const;
+        GeoLogVolPtr cacheVolume(GeoLogVolPtr vol) const;
+        GeoShapePtr cacheShape(GeoShapePtr shape) const;
+
+    private:
+        using PhysVolSet = std::set<GeoIntrusivePtr<GeoPhysVol>, GeoPhysVolSorter>;
+        using LogVolSet = std::set<GeoLogVolPtr, GeoLogVolSorter>;
+        using TrfSet = std::set<GeoTrfPtr, GeoTrf::TransformSorter>;
+        using ShapeSet = std::set<GeoShapePtr, GeoShapeSorter>;
+        mutable PhysVolSet m_physVolStore{};
+        mutable LogVolSet m_logVolStore{};
+
+        static TrfSet s_trfStore;
+        static ShapeSet s_shapeStore;
+};
+
+
+#endif
diff --git a/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/GeoShapeSorter.h b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/GeoShapeSorter.h
index 388348bec2102334401189f45c58cdb55f41e131..6c04c0ba458677fa3282924d80fad571965ab2d7 100644
--- a/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/GeoShapeSorter.h
+++ b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/GeoShapeSorter.h
@@ -40,6 +40,6 @@ struct GeoComposedShapeSorter {
 /// @brief 
 /// @tparam ShapeType 
 template<class ShapeType>
-using GeoShapeSet = std::set<GeoIntrusivePtr<const ShapeType>, GeoShapeSorter>;
+using GeoShapeSet = std::set<GeoIntrusivePtr<ShapeType>, GeoShapeSorter>;
 
 #endif
\ No newline at end of file
diff --git a/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/GeoShapeUtils.h b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/GeoShapeUtils.h
index 2fe716d13dd137cd88ddc33933160b6519b7b801..77fb6a9147c2eed9923e44f187f4584755c4eeec 100644
--- a/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/GeoShapeUtils.h
+++ b/GeoModelCore/GeoModelFuncSnippets/GeoModelFuncSnippets/GeoShapeUtils.h
@@ -25,6 +25,8 @@ GeoIntrusivePtr<const GeoShape> compressShift(const GeoShape* shift);
 ///        In the case of the GeoSubtraction all subtracting shapes
 std::vector<const GeoShape*> getBooleanComponents(const GeoShape* booleanShape);
 
-
+/// @brief Returns the edge points surrounding a shape
+std::vector<GeoTrf::Vector3D> getPolyShapeEdges(const GeoShape* shape,
+                                                const GeoTrf::Transform3D& refTrf);
 
 #endif
\ No newline at end of file
diff --git a/GeoModelCore/GeoModelFuncSnippets/src/GeoDeDuplicator.cxx b/GeoModelCore/GeoModelFuncSnippets/src/GeoDeDuplicator.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..0d48d05db8bd4d0e2929d5887f13d01413107bf8
--- /dev/null
+++ b/GeoModelCore/GeoModelFuncSnippets/src/GeoDeDuplicator.cxx
@@ -0,0 +1,26 @@
+
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "GeoModelFuncSnippets/GeoDeDuplicator.h"
+
+GeoDeDuplicator::TrfSet GeoDeDuplicator::s_trfStore{};
+GeoDeDuplicator::ShapeSet GeoDeDuplicator::s_shapeStore{};
+
+GeoDeDuplicator::GeoTrfPtr 
+    GeoDeDuplicator::makeTransform(const GeoTrf::Transform3D& trf) const {
+        return *s_trfStore.emplace(new GeoTransform(trf)).first;
+    }
+GeoDeDuplicator::GeoPhysVolPtr 
+    GeoDeDuplicator::cacheVolume(GeoPhysVolPtr vol) const {
+        return *m_physVolStore.insert(vol).first;
+    }
+GeoDeDuplicator::GeoLogVolPtr 
+    GeoDeDuplicator::cacheVolume(GeoLogVolPtr vol) const {
+        return *m_logVolStore.insert(vol).first;
+    }
+GeoDeDuplicator::GeoShapePtr 
+    GeoDeDuplicator::cacheShape(GeoShapePtr shape) const {
+        return *s_shapeStore.insert(shape).first;
+    }
diff --git a/GeoModelCore/GeoModelFuncSnippets/src/GeoShapeUtils.cxx b/GeoModelCore/GeoModelFuncSnippets/src/GeoShapeUtils.cxx
index 4ba5bffcb0eb43375ab05daebe600bdfa756beec..10ba0d3b2850e844df40222965b1789e4d141e10 100644
--- a/GeoModelCore/GeoModelFuncSnippets/src/GeoShapeUtils.cxx
+++ b/GeoModelCore/GeoModelFuncSnippets/src/GeoShapeUtils.cxx
@@ -3,6 +3,7 @@
 */
 #include "GeoModelFuncSnippets/GeoShapeUtils.h"
 #include "GeoModelFuncSnippets/TransformToStringConverter.h"
+#include "GeoModelFuncSnippets/throwExcept.h"
 
 /// Boolean volume shapes
 #include "GeoModelKernel/GeoShapeUnion.h"
@@ -19,6 +20,7 @@
 #include "GeoModelKernel/GeoCons.h"
 #include "GeoModelKernel/GeoPara.h"
 #include "GeoModelKernel/GeoTorus.h"
+#include "GeoModelKernel/GeoSimplePolygonBrep.h"
 
 #include "GeoModelKernel/Units.h"
 
@@ -139,3 +141,72 @@ std::string printGeoShape(const GeoShape* shape) {
    }
     return ostr.str();
 }
+
+std::vector<GeoTrf::Vector3D> getPolyShapeEdges(const GeoShape* shape,
+                                                const GeoTrf::Transform3D& refTrf) {
+
+    if (!shape) {
+        THROW_EXCEPTION("Nullptr was given ");
+    }
+    constexpr double boundary = 0.;
+    std::vector<GeoTrf::Vector3D> edgePoints{};
+    std::pair<const GeoShape*, const GeoShape*> ops = getOps(shape);
+    if (shape->typeID() == GeoShapeUnion::getClassTypeID()){
+        edgePoints = getPolyShapeEdges(ops.first, refTrf);
+        std::vector<GeoTrf::Vector3D> edgePoints2{getPolyShapeEdges(ops.second, refTrf)};
+        edgePoints.insert(edgePoints.end(),
+                          std::make_move_iterator(edgePoints2.begin()),
+                          std::make_move_iterator(edgePoints2.end()));
+    } else if (shape->typeID() == GeoShapeSubtraction::getClassTypeID()) {
+        return getPolyShapeEdges(ops.first, refTrf);
+    } else if (shape->typeID() == GeoBox::getClassTypeID()) {
+        edgePoints.reserve(6);
+        const GeoBox* box = static_cast<const GeoBox*>(shape);
+        for (double sX :{-1., 1.}) {
+            for (double sY :{-1., 1.}) {
+                for (double sZ: {-1., 1.}) {
+                    edgePoints.emplace_back(refTrf * GeoTrf::Vector3D{sX* (box->getXHalfLength() - boundary),
+                                                                      sY* (box->getYHalfLength() - boundary),
+                                                                      sZ* (box->getZHalfLength() - boundary)});
+                }
+            }
+        }
+    } else if (shape->typeID() == GeoShapeShift::getClassTypeID()) {
+        GeoIntrusivePtr<const GeoShape> shift = compressShift(shape);
+        const GeoShapeShift* shiftPtr = static_cast<const GeoShapeShift*>(shift.get());
+        std::vector<GeoTrf::Vector3D> shiftedEdges = getPolyShapeEdges(ops.first, shiftPtr->getX());
+        std::transform(shiftedEdges.begin(), shiftedEdges.end(), std::back_inserter(edgePoints),
+                    [&refTrf](const GeoTrf::Vector3D& shift){
+                            return refTrf * shift;
+                    });
+    } else if (shape->typeID() == GeoTrd::getClassTypeID()) {
+        const GeoTrd* trd = static_cast<const GeoTrd*>(shape);
+        edgePoints.reserve(6);
+        for (double sZ : {-1., 1.}){
+            double dX = (sZ < 0 ? trd->getXHalfLength1() : trd->getXHalfLength2()) - boundary;
+            double dY = (sZ < 0 ? trd->getYHalfLength1() : trd->getYHalfLength2()) - boundary;
+            for (double sX: {-1., 1.}) {
+                for (double sY: {-1., 1.}) {
+                    edgePoints.emplace_back(refTrf * GeoTrf::Vector3D{sX* dX, sY* dY,
+                                                                      sZ* (trd->getZHalfLength()- boundary)});
+
+                }
+            }
+            
+        }
+    } else if (shape->typeID() == GeoSimplePolygonBrep::getClassTypeID()) {
+        const GeoSimplePolygonBrep* brep = static_cast<const GeoSimplePolygonBrep*>(shape);
+        edgePoints.reserve(2* brep->getNVertices());
+        for (double sZ: {-1., 1.}) {
+            for (unsigned int vtx = 0 ; vtx < brep->getNVertices(); ++vtx){
+                edgePoints.emplace_back(brep->getXVertex(vtx),
+                                        brep->getYVertex(vtx),
+                                        sZ * brep->getDZ());
+            
+            }
+        }
+    } else {
+        THROW_EXCEPTION("The shape "<<shape->type()<<" is not supported. Please add it to the list");
+    }
+    return edgePoints;
+}
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/Element2GeoItem.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/Element2GeoItem.h
index 8b084f856e70a5e6a18725086119bb832c4eacce..86cd6ed8f5b0f42491dcc9baa647bce67d275bee 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/Element2GeoItem.h
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/Element2GeoItem.h
@@ -11,6 +11,10 @@
 #define GEO_MODEL_XML_ELEMENT2GEO_ITEM_H
 #include <xercesc/util/XercesDefs.hpp>
 
+#include "GeoModelFuncSnippets/GeoDeDuplicator.h"
+#include "GeoModelKernel/RCBase.h"
+#include "GeoModelKernel/GeoIntrusivePtr.h"
+
 #include <map>
 #include <string>
 
@@ -23,14 +27,15 @@ XERCES_CPP_NAMESPACE_END
 class ProcessorRegistry;
 namespace HepTool {class Evaluator;}
 
-class Element2GeoItem {
+class Element2GeoItem: public GeoDeDuplicator {
 
 public:
-    Element2GeoItem();
-    virtual ~Element2GeoItem();
+    Element2GeoItem() = default;
+    virtual ~Element2GeoItem() = default;;
     RCBase * process(const xercesc::DOMElement *element, GmxUtil &gmxUtil);
     virtual RCBase * make(const xercesc::DOMElement *element, GmxUtil &gmxUtil) const;
 protected:
-    std::map<std::string, RCBase *> m_map;  
+    using EntryMap = std::map<std::string, GeoIntrusivePtr<RCBase>>;
+    EntryMap m_map{};  
 };
 #endif // ELEMENT2GEO_ITEM_H
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/ElementProcessor.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/ElementProcessor.h
index 08c92612ac39c52b926a019c51782981d34e7bb1..5b3a71c7e55ec8e5c6ce59f968abf6a3b59b04cf 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/ElementProcessor.h
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/ElementProcessor.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 
 //
@@ -12,13 +12,13 @@
 #include <xercesc/util/XercesDefs.hpp>
 
 #include "GeoModelXml/GeoNodeList.h"
-
+#include "GeoModelFuncSnippets/GeoDeDuplicator.h"
 XERCES_CPP_NAMESPACE_BEGIN
 class DOMElement;
 XERCES_CPP_NAMESPACE_END
 class GmxUtil;
 
-class ElementProcessor {
+class ElementProcessor: public GeoDeDuplicator {
 
 public:
     ElementProcessor();
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/Gmx2Geo.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/Gmx2Geo.h
index 30a90db1f26d11f978886729a864272addea3097..9ad3f0f38f7e140fe7fdaae51e0b6b9cd4a13bed 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/Gmx2Geo.h
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/Gmx2Geo.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef GEO_MODEL_XML_GMX2GEO_H
@@ -54,15 +54,15 @@ XERCES_CPP_NAMESPACE_END
 
 class IEvaluator;
 
-#define processorList std::map<std::string,ElementProcessor*> 
+using processorList = std::map<std::string,ElementProcessor*>;
 
 class Gmx2Geo {
 public:
     Gmx2Geo(const std::string& gmxFile, GeoVPhysVol *addHere, GmxInterface &gmxInterface, unsigned int flags = 0, bool useMatManager = 0, std::string levelMapName = "", const processorList& procs=processorList());
 private:
 // Disallow copying
-    Gmx2Geo(const Gmx2Geo &right);
-    Gmx2Geo & operator=(const Gmx2Geo &right);
+    Gmx2Geo(const Gmx2Geo &right) = delete;
+    Gmx2Geo & operator=(const Gmx2Geo &right) = delete;
 
     int doDefines(xercesc::DOMDocument *doc, GeoModelTools::IEvaluator &eval);
     int doPositionIndex(xercesc::DOMDocument *doc, GmxUtil &gmxUtil, std::string levelMapName = "");
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/src/Element2GeoItem.cxx b/GeoModelTools/GeoModelXML/GeoModelXml/src/Element2GeoItem.cxx
index 7ed20e61ba28671b49f3964bc3ad98d568003378..d37668328a51cd26c9fcb40f390b451d3e5d08df 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/src/Element2GeoItem.cxx
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/src/Element2GeoItem.cxx
@@ -12,13 +12,11 @@
 
 #include "GeoModelXml/GmxUtil.h"
 #include "GeoModelKernel/RCBase.h"
+#include "GeoModelFuncSnippets/throwExcept.h"
 
 using namespace std;
 using namespace xercesc;
 
-Element2GeoItem::Element2GeoItem() {}
-
-Element2GeoItem::~Element2GeoItem() {}
 
 RCBase * Element2GeoItem::process(const xercesc::DOMElement *element, GmxUtil &gmxUtil) {
 
@@ -30,12 +28,11 @@ RCBase * Element2GeoItem::process(const xercesc::DOMElement *element, GmxUtil &g
     XMLString::release(&name2release);
     XMLString::release(&name_tmp);
 
-    RCBase *item;
-    map<string, RCBase *>::iterator entry;
-    if (name == "") { // Unnamed item; cannot store in the map; make a new one 
+    RCBase *item{nullptr};
+    EntryMap::iterator entry;
+    if (name.empty()) { // Unnamed item; cannot store in the map; make a new one 
         item = make(element, gmxUtil);
-    }
-    else if ((entry = m_map.find(name)) == m_map.end()) { // Not in; make a new one
+    } else if ((entry = m_map.find(name)) == m_map.end()) { // Not in; make a new one
         item = make(element, gmxUtil);
         m_map[name] = item; // And put it in the map
     }
@@ -48,8 +45,7 @@ RCBase * Element2GeoItem::process(const xercesc::DOMElement *element, GmxUtil &g
 
 RCBase * Element2GeoItem::make(const xercesc::DOMElement *element, GmxUtil & /* gmxUtil */) const {
     char *name2release = XMLString::transcode(element->getNodeName());
-    msglog << MSG::FATAL << "Oh oh: called base class make() method of Element2GeoType object; tag " << name2release << endmsg;
+    std::string nodeName{name2release};
     XMLString::release(&name2release);
-
-    std::abort();
+    THROW_EXCEPTION("Oh oh: called base class make() method of Element2GeoType object; tag " << nodeName);
 }