diff --git a/Applications/DataExplorer/VtkAct/CMakeLists.txt b/Applications/DataExplorer/VtkAct/CMakeLists.txt
index 4c5d2a0433b109fba1ba4747c1d793256380192c..222f9f36ff5df6cd08206a187be17cf492904443 100644
--- a/Applications/DataExplorer/VtkAct/CMakeLists.txt
+++ b/Applications/DataExplorer/VtkAct/CMakeLists.txt
@@ -12,7 +12,7 @@ include_directories(
     ${CMAKE_CURRENT_SOURCE_DIR}/../../BaseLib
     ${CMAKE_CURRENT_SOURCE_DIR}/../../GeoLib
     ${CMAKE_CURRENT_SOURCE_DIR}/../../FileIO
-    ${CMAKE_CURRENT_SOURCE_DIR}/../../FileIO/GmshIO
+    ${CMAKE_CURRENT_SOURCE_DIR}/../../FileIO/Gmsh
     ${CMAKE_CURRENT_SOURCE_DIR}/../../MeshLib
     ${CMAKE_CURRENT_SOURCE_DIR}/../../MathLib
     ${CMAKE_CURRENT_SOURCE_DIR}/../VtkVis
diff --git a/Applications/DataExplorer/mainwindow.cpp b/Applications/DataExplorer/mainwindow.cpp
index 81ec73a23d38ad1d63c585fb580b5a8e63ff9d0d..892f39d5e9739caff8499c46441f2a82d77c40eb 100644
--- a/Applications/DataExplorer/mainwindow.cpp
+++ b/Applications/DataExplorer/mainwindow.cpp
@@ -64,10 +64,11 @@
 #include "MeshLib/IO/FEFLOW/FEFLOWMeshInterface.h"
 #include "MeshLib/IO/Legacy/MeshIO.h"
 #include "MeshLib/IO/readMeshFromFile.h"
-#include "FileIO/GMSHInterface.h"
+#include "MeshLib/IO/GmshReader.h"
 #include "FileIO/TetGenInterface.h"
 #include "PetrelInterface.h"
 #include "XmlIO/Qt/XmlGspInterface.h"
+#include "GeoLib/IO/GMSHInterface.h"
 #include "GeoLib/IO/FEFLOW/FEFLOWGeoInterface.h"
 #include "GeoLib/IO/XmlIO/Qt/XmlGmlInterface.h"
 #include "GeoLib/IO/XmlIO/Qt/XmlStnInterface.h"
@@ -429,10 +430,10 @@ void MainWindow::save()
         std::vector<std::string> selected_geometries;
         _project.getGEOObjects().getGeometryNames(selected_geometries);
 
-        GMSHInterface gmsh_io(
+        GeoLib::IO::GMSHInterface gmsh_io(
             _project.getGEOObjects(), true,
-            FileIO::GMSH::MeshDensityAlgorithm::AdaptiveMeshDensity,
-            0.05, 0.5, 2, selected_geometries);
+            GeoLib::IO::GMSH::MeshDensityAlgorithm::AdaptiveMeshDensity, 0.05,
+            0.5, 2, selected_geometries);
         gmsh_io.setPrecision(std::numeric_limits<double>::digits10);
         bool const success = gmsh_io.writeToFile(fileName.toStdString());
 
@@ -565,9 +566,9 @@ void MainWindow::loadFile(ImportFileType::type t, const QString &fileName)
     else if (t == ImportFileType::GMSH)
     {
         std::string msh_name (fileName.toStdString());
-        if (FileIO::GMSHInterface::isGMSHMeshFile (msh_name))
+        if (MeshLib::IO::GMSH::isGMSHMeshFile (msh_name))
         {
-            std::unique_ptr<MeshLib::Mesh> mesh(FileIO::GMSHInterface::readGMSHMesh(msh_name));
+            std::unique_ptr<MeshLib::Mesh> mesh(MeshLib::IO::GMSH::readGMSHMesh(msh_name));
             if (mesh)
                 _meshModel->addMesh(std::move(mesh));
             else
@@ -901,16 +902,16 @@ void MainWindow::callGMSH(std::vector<std::string> & selectedGeometries,
         if (!fileName.isEmpty())
         {
             if (param4 == -1) { // adaptive meshing selected
-                GMSHInterface gmsh_io(
+                GeoLib::IO::GMSHInterface gmsh_io(
                     _project.getGEOObjects(), true,
-                    FileIO::GMSH::MeshDensityAlgorithm::AdaptiveMeshDensity,
+                    GeoLib::IO::GMSH::MeshDensityAlgorithm::AdaptiveMeshDensity,
                     param2, param3, param1, selectedGeometries);
                 gmsh_io.setPrecision(std::numeric_limits<double>::digits10);
                 gmsh_io.writeToFile(fileName.toStdString());
             } else { // homogeneous meshing selected
-                GMSHInterface gmsh_io(
+                GeoLib::IO::GMSHInterface gmsh_io(
                     _project.getGEOObjects(), true,
-                    FileIO::GMSH::MeshDensityAlgorithm::FixedMeshDensity,
+                    GeoLib::IO::GMSH::MeshDensityAlgorithm::FixedMeshDensity,
                     param4, param3, param1, selectedGeometries);
                 gmsh_io.setPrecision(std::numeric_limits<double>::digits10);
                 gmsh_io.writeToFile(fileName.toStdString());
diff --git a/Applications/Utils/FileConverter/CMakeLists.txt b/Applications/Utils/FileConverter/CMakeLists.txt
index 1a2bca68837f80b2e88f848bb144011d55c21e56..1177f49dee479579a5693fcc8fa5a099446dcf47 100644
--- a/Applications/Utils/FileConverter/CMakeLists.txt
+++ b/Applications/Utils/FileConverter/CMakeLists.txt
@@ -30,7 +30,7 @@ set_target_properties(generateMatPropsFromMatID
 
 add_executable(GMSH2OGS GMSH2OGS.cpp)
 set_target_properties(GMSH2OGS PROPERTIES FOLDER Utilities)
-target_link_libraries(GMSH2OGS MeshLib FileIO)
+target_link_libraries(GMSH2OGS MeshLib)
 ADD_VTK_DEPENDENCY(GMSH2OGS)
 
 add_executable(OGS2VTK OGS2VTK.cpp)
diff --git a/Applications/Utils/FileConverter/GMSH2OGS.cpp b/Applications/Utils/FileConverter/GMSH2OGS.cpp
index 5fbdaa41658af5fcf96bc778ba569cb509a57e7d..0fa07708d33d12cd7dffe35691136c56748a727a 100644
--- a/Applications/Utils/FileConverter/GMSH2OGS.cpp
+++ b/Applications/Utils/FileConverter/GMSH2OGS.cpp
@@ -28,8 +28,7 @@
 #include "MemWatch.h"
 #endif
 
-// FileIO
-#include "FileIO/GMSHInterface.h"
+#include "MeshLib/IO/GmshReader.h"
 
 #include "MeshLib/IO/writeMeshToFile.h"
 #include "MeshLib/MeshSearch/ElementSearch.h"
@@ -74,7 +73,8 @@ int main (int argc, char* argv[])
 #endif
     BaseLib::RunTime run_time;
     run_time.start();
-    MeshLib::Mesh * mesh(FileIO::GMSHInterface::readGMSHMesh(gmsh_mesh_arg.getValue()));
+    MeshLib::Mesh* mesh(
+        MeshLib::IO::GMSH::readGMSHMesh(gmsh_mesh_arg.getValue()));
 
     if (mesh == nullptr) {
         INFO("Could not read mesh from %s.", gmsh_mesh_arg.getValue().c_str());
diff --git a/Applications/Utils/MeshEdit/CMakeLists.txt b/Applications/Utils/MeshEdit/CMakeLists.txt
index 498254606b643858aac0b03bf7fbbed6b805be07..0d90cbe2f2f61c890558679275a274b47cb803df 100644
--- a/Applications/Utils/MeshEdit/CMakeLists.txt
+++ b/Applications/Utils/MeshEdit/CMakeLists.txt
@@ -3,7 +3,7 @@ include_directories(
     ${CMAKE_SOURCE_DIR}/BaseLib
     ${CMAKE_SOURCE_DIR}/GeoLib
     ${CMAKE_SOURCE_DIR}/FileIO
-    ${CMAKE_SOURCE_DIR}/FileIO/GmshIO
+    ${CMAKE_SOURCE_DIR}/FileIO/Gmsh
     ${CMAKE_SOURCE_DIR}/MathLib
     ${CMAKE_SOURCE_DIR}/MeshLib
 )
diff --git a/FileIO/CMakeLists.txt b/FileIO/CMakeLists.txt
index 6a6117542348ea7c4adf4d1853bc35b98d99190a..7f536a633106301d214dc118de1b5050c3437bb9 100644
--- a/FileIO/CMakeLists.txt
+++ b/FileIO/CMakeLists.txt
@@ -1,7 +1,5 @@
 GET_SOURCE_FILES(SOURCES_FileIO)
 set(SOURCES ${SOURCES_FileIO})
-GET_SOURCE_FILES(SOURCES_GMSHIO GmshIO)
-set(SOURCES ${SOURCES} ${SOURCES_GMSHIO})
 
 # Create the library
 add_library(FileIO ${SOURCES})
diff --git a/GeoLib/CMakeLists.txt b/GeoLib/CMakeLists.txt
index 8b6cc0586753a94b9ea8afd912174faa68e283de..64bb24741980bc1d0059f19c8f4fdf68661f364e 100644
--- a/GeoLib/CMakeLists.txt
+++ b/GeoLib/CMakeLists.txt
@@ -18,6 +18,9 @@ if(QT4_FOUND)
     SET(SOURCES ${SOURCES} ${SOURCES_IO_FEFLOW})
 endif()
 
+GET_SOURCE_FILES(SOURCES_IO_GMSHIO IO/Gmsh)
+set(SOURCES ${SOURCES} ${SOURCES_IO_GMSHIO})
+
 # Create the library
 add_library(GeoLib STATIC ${SOURCES}
     ${CMAKE_CURRENT_SOURCE_DIR}/../ThirdParty/tetgen/predicates.cxx
diff --git a/FileIO/GMSHInterface.cpp b/GeoLib/IO/GMSHInterface.cpp
similarity index 50%
rename from FileIO/GMSHInterface.cpp
rename to GeoLib/IO/GMSHInterface.cpp
index e643159933babdb89667c148121a690bed4dd048..3f0923909ca8d54bf5a87fe3e914a5417976b751 100644
--- a/FileIO/GMSHInterface.cpp
+++ b/GeoLib/IO/GMSHInterface.cpp
@@ -15,28 +15,23 @@
 
 #include "BaseLib/BuildInfo.h"
 #include "BaseLib/FileTools.h"
-#include "BaseLib/StringTools.h"
 
-#include "FileIO/GMSHInterface.h"
-#include "FileIO/GmshIO/GMSHAdaptiveMeshDensity.h"
-#include "FileIO/GmshIO/GMSHFixedMeshDensity.h"
+#include "GeoLib/IO/GMSHInterface.h"
+#include "GeoLib/IO/Gmsh/GMSHAdaptiveMeshDensity.h"
+#include "GeoLib/IO/Gmsh/GMSHFixedMeshDensity.h"
+#include "GeoLib/IO/Gmsh/GMSHPoint.h"
+#include "GeoLib/IO/Gmsh/GMSHPolygonTree.h"
+#include "GeoLib/IO/Gmsh/GMSHMeshDensityStrategy.h"
 
 #include "GeoLib/AnalyticalGeometry.h"
 #include "GeoLib/GEOObjects.h"
-#include "GeoLib/Point.h"
 #include "GeoLib/Polygon.h"
-#include "GeoLib/Polyline.h"
 #include "GeoLib/PolylineWithSegmentMarker.h"
 #include "GeoLib/PolygonWithSegmentMarker.h"
 
-#include "MathLib/LinAlg/Solvers/GaussAlgorithm.h"
-
-#include "MeshLib/Elements/Elements.h"
-#include "MeshLib/Mesh.h"
-#include "MeshLib/MeshEditing/ElementValueModification.h"
-#include "MeshLib/Node.h"
-
-namespace FileIO
+namespace GeoLib
+{
+namespace IO
 {
 GMSHInterface::GMSHInterface(GeoLib::GEOObjects& geo_objs,
                              bool /*include_stations_as_constraints*/,
@@ -70,240 +65,6 @@ GMSHInterface::~GMSHInterface()
         delete polygon_tree;
 }
 
-bool GMSHInterface::isGMSHMeshFile(const std::string& fname)
-{
-    std::ifstream input(fname.c_str());
-
-    if (!input) {
-        ERR("GMSHInterface::isGMSHMeshFile(): Could not open file %s.", fname.c_str());
-        return false;
-    }
-
-    std::string header_first_line;
-    input >> header_first_line;
-    if (header_first_line.find("$MeshFormat") != std::string::npos) {
-        // read version
-        std::string version;
-        getline(input, version);
-        getline(input, version);
-        INFO("GMSHInterface::isGMSHMeshFile(): Found GMSH mesh file version: %s.",
-             version.c_str());
-        input.close();
-        return true;
-    }
-
-    return false;
-}
-
-MeshLib::Mesh* GMSHInterface::readGMSHMesh(std::string const& fname)
-{
-    std::string line;
-    std::ifstream in(fname.c_str(), std::ios::in);
-    if (!in.is_open())
-    {
-        WARN ("GMSHInterface::readGMSHMesh() - Could not open file %s.", fname.c_str());
-        return nullptr;
-    }
-
-    getline(in, line); // $MeshFormat keyword
-    if (line.find("$MeshFormat") == std::string::npos)
-    {
-        in.close();
-        WARN ("No GMSH file format recognized.");
-        return nullptr;
-    }
-
-    getline(in, line); // version-number file-type data-size
-    if (line.substr(0,3).compare("2.2") != 0) {
-        WARN("Wrong gmsh file format version.");
-        return nullptr;
-    }
-
-    if (line.substr(4,1).compare("0") != 0) {
-        WARN("Currently reading gmsh binary file type is not supported.");
-        return nullptr;
-    }
-    getline(in, line); //$EndMeshFormat
-
-    std::vector<MeshLib::Node*> nodes;
-    std::vector<MeshLib::Element*> elements;
-    std::vector<int> materials;
-    std::map<unsigned, unsigned> id_map;
-    while (line.find("$EndElements") == std::string::npos)
-    {
-        // Node data
-        getline(in, line); //$Nodes Keywords
-        if (line.find("$Nodes") != std::string::npos)
-        {
-            std::size_t n_nodes(0);
-            long id;
-            double x, y, z;
-            in >> n_nodes >> std::ws;
-            nodes.resize(n_nodes);
-            for (std::size_t i = 0; i < n_nodes; i++) {
-                in >> id >> x >> y >> z >> std::ws;
-                id_map.insert(std::map<unsigned, unsigned>::value_type(id, i));
-                nodes[i] = new MeshLib::Node(x,y,z,id);
-            }
-            getline(in, line); // End Node keyword $EndNodes
-        }
-
-        // Element data
-        if (line.find("$Elements") != std::string::npos)
-        {
-            std::size_t n_elements(0);
-            if (! (in >> n_elements >> std::ws)) { // number-of-elements
-                ERR("Read GMSH mesh does not contain any elements");
-            }
-            elements.reserve(n_elements);
-            materials.reserve(n_elements);
-            for (std::size_t i = 0; i < n_elements; i++)
-            {
-                MeshLib::Element* elem(nullptr);
-                int mat_id(0);
-                std::tie(elem, mat_id) = readElement(in, nodes, id_map);
-
-                if (elem) {
-                    elements.push_back(elem);
-                    materials.push_back(mat_id);
-                }
-            }
-            getline(in, line); // END keyword
-        }
-
-        if (line.find("PhysicalNames") != std::string::npos)
-        {
-            std::size_t n_lines(0);
-            in >> n_lines >> std::ws; // number-of-lines
-            for (std::size_t i = 0; i < n_lines; i++)
-                getline(in, line);
-            getline(in, line); // END keyword
-        }
-    }
-    in.close();
-    if (elements.empty()) {
-        for (auto it(nodes.begin()); it != nodes.end(); ++it) {
-            delete *it;
-        }
-        return nullptr;
-    }
-
-    MeshLib::Mesh * mesh(new MeshLib::Mesh(
-        BaseLib::extractBaseNameWithoutExtension(fname), nodes, elements));
-
-    boost::optional<MeshLib::PropertyVector<int> &> opt_material_ids(
-        mesh->getProperties().createNewPropertyVector<int>(
-            "MaterialIDs", MeshLib::MeshItemType::Cell, 1)
-    );
-    if (!opt_material_ids) {
-        WARN("Could not create PropertyVector for MaterialIDs in Mesh.");
-    } else {
-        MeshLib::PropertyVector<int> & material_ids(opt_material_ids.get());
-        material_ids.insert(material_ids.end(), materials.cbegin(),
-            materials.cend());
-    }
-
-    MeshLib::ElementValueModification::condense(*mesh);
-
-    INFO("\t... finished.");
-    INFO("Nr. Nodes: %d.", nodes.size());
-    INFO("Nr. Elements: %d.", elements.size());
-
-    return mesh;
-}
-
-void GMSHInterface::readNodeIDs(std::ifstream &in,
-                                unsigned n_nodes,
-                                std::vector<unsigned> &node_ids,
-                                std::map<unsigned, unsigned> const& id_map)
-{
-    unsigned idx;
-    for (unsigned i = 0; i < n_nodes; i++)
-    {
-        in >> idx;
-        node_ids.push_back(id_map.at(idx));
-    }
-}
-
-std::pair<MeshLib::Element*, int>
-GMSHInterface::readElement(std::ifstream &in,
-    std::vector<MeshLib::Node*> const& nodes,
-    std::map<unsigned, unsigned> const& id_map)
-{
-    unsigned idx, type, n_tags, dummy;
-    int mat_id;
-    std::vector<unsigned> node_ids;
-    std::vector<MeshLib::Node*> elem_nodes;
-    in >> idx >> type >> n_tags >> mat_id >> dummy;
-
-    // skip tags
-    for (std::size_t j = 2; j < n_tags; j++)
-        in >> dummy;
-
-    switch (type)
-    {
-    case 1: {
-        readNodeIDs(in, 2, node_ids, id_map);
-        // edge_nodes array will be deleted from Line object
-        auto edge_nodes = new MeshLib::Node*[2];
-        edge_nodes[0] = nodes[node_ids[0]];
-        edge_nodes[1] = nodes[node_ids[1]];
-        return std::make_pair(new MeshLib::Line(edge_nodes), mat_id);
-    }
-    case 2: {
-        readNodeIDs(in, 3, node_ids, id_map);
-        auto tri_nodes = new MeshLib::Node*[3];
-        tri_nodes[0] = nodes[node_ids[2]];
-        tri_nodes[1] = nodes[node_ids[1]];
-        tri_nodes[2] = nodes[node_ids[0]];
-        return std::make_pair(new MeshLib::Tri(tri_nodes), mat_id);
-    }
-    case 3: {
-        readNodeIDs(in, 4, node_ids, id_map);
-        auto quad_nodes = new MeshLib::Node*[4];
-        for (unsigned k(0); k < 4; k++)
-            quad_nodes[k] = nodes[node_ids[k]];
-        return std::make_pair(new MeshLib::Quad(quad_nodes), mat_id);
-    }
-    case 4: {
-        readNodeIDs(in, 4, node_ids, id_map);
-        auto tet_nodes = new MeshLib::Node*[5];
-        for (unsigned k(0); k < 4; k++)
-            tet_nodes[k] = nodes[node_ids[k]];
-        return std::make_pair(new MeshLib::Tet(tet_nodes), mat_id);
-    }
-    case 5: {
-        readNodeIDs(in, 8, node_ids, id_map);
-        auto hex_nodes = new MeshLib::Node*[8];
-        for (unsigned k(0); k < 8; k++)
-            hex_nodes[k] = nodes[node_ids[k]];
-        return std::make_pair(new MeshLib::Hex(hex_nodes), mat_id);
-    }
-    case 6: {
-        readNodeIDs(in, 6, node_ids, id_map);
-        auto prism_nodes = new MeshLib::Node*[6];
-        for (unsigned k(0); k < 6; k++)
-            prism_nodes[k] = nodes[node_ids[k]];
-        return std::make_pair(new MeshLib::Prism(prism_nodes), mat_id);
-    }
-    case 7: {
-        readNodeIDs(in, 5, node_ids, id_map);
-        auto pyramid_nodes = new MeshLib::Node*[5];
-        for (unsigned k(0); k < 5; k++)
-            pyramid_nodes[k] = nodes[node_ids[k]];
-        return std::make_pair(new MeshLib::Pyramid(pyramid_nodes), mat_id);
-    }
-    case 15:
-        in >> dummy; // skip rest of line
-        break;
-    default:
-        WARN("GMSHInterface::readGMSHMesh(): Unknown element type %d.", type);
-        break;
-    }
-    return std::make_pair(nullptr, -1);
-}
-
-
 bool GMSHInterface::write()
 {
     _out << "// GMSH input file created by OpenGeoSys " << BaseLib::BuildInfo::git_describe;
@@ -485,4 +246,5 @@ void GMSHInterface::writePoints(std::ostream& out) const
     }
 }
 
-} // end namespace FileIO
+} // end namespace IO
+} // end namespace GeoLib
diff --git a/FileIO/GMSHInterface.h b/GeoLib/IO/GMSHInterface.h
similarity index 71%
rename from FileIO/GMSHInterface.h
rename to GeoLib/IO/GMSHInterface.h
index 78bc53ca0b15d5af78dd13fd9a27a1a09ab415f2..2159b74338e518287478a18a4fef869dd1a0af3a 100644
--- a/FileIO/GMSHInterface.h
+++ b/GeoLib/IO/GMSHInterface.h
@@ -1,8 +1,4 @@
 /**
- * \file
- * \author Thomas Fischer
- * \date   2010-04-29
- * \brief  Definition of the GMSHInterface class.
  *
  * \copyright
  * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
@@ -15,34 +11,26 @@
 #ifndef GMSHINTERFACE_H_
 #define GMSHINTERFACE_H_
 
-#include <list>
-#include <map>
-#include <string>
+#include <iosfwd>
 
 #include "BaseLib/IO/Writer.h"
-#include "FileIO/GmshIO/GMSHPoint.h"
-#include "FileIO/GmshIO/GMSHPolygonTree.h"
-#include "FileIO/GmshIO/GMSHMeshDensityStrategy.h"
 
 #include "MathLib/LinAlg/Dense/DenseMatrix.h"
 
 namespace GeoLib
 {
-    class GEOObjects;
-    class Polygon;
-}
+class GEOObjects;
+class Polygon;
 
-namespace MeshLib
+namespace IO
 {
-    class Mesh;
-    class Element;
-    class Node;
-}
 
-namespace FileIO
+namespace GMSH
 {
 
-namespace GMSH {
+class GMSHPoint;
+class GMSHPolygonTree;
+class GMSHMeshDensityStrategy;
 
 enum class MeshDensityAlgorithm {
     FixedMeshDensity, //!< set the parameter with a fixed value
@@ -91,29 +79,10 @@ public:
 
     ~GMSHInterface();
 
-    /**
-     * checks if there is a GMSH mesh file header
-     * @param fname the file name of the mesh (including the path)
-     * @return true, if the file seems to be a valid GMSH file, else false
-     */
-    static bool isGMSHMeshFile (const std::string& fname);
-    /**
-     * reads a mesh created by GMSH - this implementation is based on the former function GMSH2MSH
-     * @param fname the file name of the mesh (including the path)
-     * @return
-     */
-    static MeshLib::Mesh* readGMSHMesh (std::string const& fname);
-
 protected:
     bool write();
 
 private:
-    /// Reads a mesh element from the input stream
-    static std::pair<MeshLib::Element*, int> readElement(
-        std::ifstream& in,
-        std::vector<MeshLib::Node*> const& nodes,
-        std::map<unsigned, unsigned> const& id_map);
-
     /**
      * 1. get and merge data from _geo_objs
      * 2. compute topological hierarchy
@@ -124,10 +93,6 @@ private:
      */
     int writeGMSHInputFile(std::ostream & out);
 
-    static void readNodeIDs(std::ifstream& in, unsigned n_nodes,
-                            std::vector<unsigned>& node_ids,
-                            std::map<unsigned, unsigned> const& id_map);
-
     void writePoints(std::ostream& out) const;
 
     std::size_t _n_lines;
@@ -138,7 +103,7 @@ private:
     std::string _gmsh_geo_name;
     std::list<GMSH::GMSHPolygonTree*> _polygon_tree_list;
 
-    std::vector<FileIO::GMSH::GMSHPoint*> _gmsh_pnts;
+    std::vector<GMSH::GMSHPoint*> _gmsh_pnts;
 
     GMSH::GMSHMeshDensityStrategy *_mesh_density_strategy;
     /// Holds the inverse rotation matrix. The matrix is used in writePoints() to
@@ -150,6 +115,7 @@ private:
     bool _rotate = false;
     bool _keep_preprocessed_geometry = true;
 };
-}
+} // end namespace IO
+} // end namespace GeoLib
 
 #endif /* GMSHINTERFACE_H_ */
diff --git a/FileIO/GmshIO/GMSHAdaptiveMeshDensity.cpp b/GeoLib/IO/Gmsh/GMSHAdaptiveMeshDensity.cpp
similarity index 96%
rename from FileIO/GmshIO/GMSHAdaptiveMeshDensity.cpp
rename to GeoLib/IO/Gmsh/GMSHAdaptiveMeshDensity.cpp
index 21cdc00dde2dad9bf1ec6e6feff6a75e7abffcc3..4010a7736c181d2362406ee94fc9f05017ed482e 100644
--- a/FileIO/GmshIO/GMSHAdaptiveMeshDensity.cpp
+++ b/GeoLib/IO/Gmsh/GMSHAdaptiveMeshDensity.cpp
@@ -1,8 +1,4 @@
 /**
- * \file
- * \author Thomas Fischer
- * \date   2012-03-05
- * \brief  Implementation of the GMSHAdaptiveMeshDensity class.
  *
  * \copyright
  * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
@@ -21,7 +17,6 @@
 
 #include <logog/include/logog.hpp>
 
-
 #include "GeoLib/Point.h"
 #include "GeoLib/Polygon.h"
 #ifndef NDEBUG
@@ -31,9 +26,12 @@
 
 #include "MathLib/MathTools.h"
 
-namespace FileIO
+namespace GeoLib
+{
+namespace IO
+{
+namespace GMSH
 {
-namespace GMSH {
 
 GMSHAdaptiveMeshDensity::GMSHAdaptiveMeshDensity(double pnt_density, double station_density,
                                                  std::size_t max_pnts_per_leaf) :
@@ -161,4 +159,5 @@ void GMSHAdaptiveMeshDensity::getQuadTreeGeometry(std::vector<GeoLib::Point*> &p
 #endif
 }
 
-} // end namespace FileIO
+} // end namespace IO
+} // end namespace GeoLib
diff --git a/FileIO/GmshIO/GMSHAdaptiveMeshDensity.h b/GeoLib/IO/Gmsh/GMSHAdaptiveMeshDensity.h
similarity index 83%
rename from FileIO/GmshIO/GMSHAdaptiveMeshDensity.h
rename to GeoLib/IO/Gmsh/GMSHAdaptiveMeshDensity.h
index d2d878a006189f5547e6322fbf9e7497ede0a706..7eaaefe98d1d7f4c9636219849fb78efdbf8a9f9 100644
--- a/FileIO/GmshIO/GMSHAdaptiveMeshDensity.h
+++ b/GeoLib/IO/Gmsh/GMSHAdaptiveMeshDensity.h
@@ -1,8 +1,4 @@
 /**
- * \file
- * \author Thomas Fischer
- * \date   2012-03-05
- * \brief  Definition of the GMSHAdaptiveMeshDensity class.
  *
  * \copyright
  * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
@@ -15,22 +11,21 @@
 #ifndef GMSHADAPTIVEMESHDENSITY_H_
 #define GMSHADAPTIVEMESHDENSITY_H_
 
-// FileIO
 #include "GMSHMeshDensityStrategy.h"
 
 namespace GeoLib
 {
-    class Polygon;
-    class Point;
-    template <typename T> class QuadTree;
+class Polygon;
+class Point;
+template <typename T> class QuadTree;
 #ifndef NDEBUG
-    class Polyline;
+class Polyline;
 #endif
-}
 
-namespace FileIO
+namespace IO
+{
+namespace GMSH
 {
-namespace GMSH {
 
 class GMSHAdaptiveMeshDensity : public GMSHMeshDensityStrategy
 {
@@ -58,6 +53,7 @@ private:
 };
 
 }
-} // end namespace FileIO
+} // end namespace IO
+} // end namespace GeoLib
 
 #endif /* GMSHADAPTIVEMESHDENSITY_H_ */
diff --git a/FileIO/GmshIO/GMSHFixedMeshDensity.cpp b/GeoLib/IO/Gmsh/GMSHFixedMeshDensity.cpp
similarity index 77%
rename from FileIO/GmshIO/GMSHFixedMeshDensity.cpp
rename to GeoLib/IO/Gmsh/GMSHFixedMeshDensity.cpp
index 59d6fbc682a79218389d407bdcf321f87d73ee47..8aba83bb2b2207518f2cc14c2199a8e9ed9cf192 100644
--- a/FileIO/GmshIO/GMSHFixedMeshDensity.cpp
+++ b/GeoLib/IO/Gmsh/GMSHFixedMeshDensity.cpp
@@ -1,8 +1,4 @@
 /**
- * \file
- * \author Thomas Fischer
- * \date   2012-03-05
- * \brief  Implementation of the GMSHFixedMeshDensity class.
  *
  * \copyright
  * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
@@ -12,11 +8,14 @@
  *
  */
 
-#include "GmshIO/GMSHFixedMeshDensity.h"
+#include "GMSHFixedMeshDensity.h"
 
-namespace FileIO
+namespace GeoLib
+{
+namespace IO
+{
+namespace GMSH
 {
-namespace GMSH {
 
 GMSHFixedMeshDensity::GMSHFixedMeshDensity(double mesh_density) :
     _mesh_density(mesh_density)
@@ -40,4 +39,5 @@ double GMSHFixedMeshDensity::getMeshDensityAtStation(GeoLib::Point const*const)
 }
 
 }
-} // end namespace FileIO
+} // end namespace IO
+} // end namespace GeoLib
diff --git a/FileIO/GmshIO/GMSHFixedMeshDensity.h b/GeoLib/IO/Gmsh/GMSHFixedMeshDensity.h
similarity index 84%
rename from FileIO/GmshIO/GMSHFixedMeshDensity.h
rename to GeoLib/IO/Gmsh/GMSHFixedMeshDensity.h
index 8644b636fe14bc44b0196a61636e6e1854ecdd1a..ce083a102cda2b72a227459756a8e35b89f0f920 100644
--- a/FileIO/GmshIO/GMSHFixedMeshDensity.h
+++ b/GeoLib/IO/Gmsh/GMSHFixedMeshDensity.h
@@ -1,8 +1,4 @@
 /**
- * \file
- * \author Thomas Fischer
- * \date   2012-03-05
- * \brief  Definition of the GMSHFixedMeshDensity class.
  *
  * \copyright
  * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
@@ -17,9 +13,12 @@
 
 #include "GMSHMeshDensityStrategy.h"
 
-namespace FileIO
+namespace GeoLib
+{
+namespace IO
+{
+namespace GMSH
 {
-namespace GMSH {
 
 class GMSHFixedMeshDensity : public GMSHMeshDensityStrategy
 {
@@ -35,6 +34,7 @@ private:
 };
 
 }
-}
+} // end namespace IO
+} // end namespace GeoLib
 
 #endif /* GMSHFIXEDMESHDENSITY_H_ */
diff --git a/FileIO/GmshIO/GMSHLine.cpp b/GeoLib/IO/Gmsh/GMSHLine.cpp
similarity index 82%
rename from FileIO/GmshIO/GMSHLine.cpp
rename to GeoLib/IO/Gmsh/GMSHLine.cpp
index 59b0e0bc46b211072079f1ed99a258ea93513916..d54864be2700802b863068e7c0d535c7d2f988bc 100644
--- a/FileIO/GmshIO/GMSHLine.cpp
+++ b/GeoLib/IO/Gmsh/GMSHLine.cpp
@@ -1,8 +1,4 @@
 /**
- * \file
- * \author Thomas Fischer
- * \date   Mar 22, 2012
- * \brief  Implementation of the GMSHLine class.
  *
  * \copyright
  * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
@@ -15,9 +11,12 @@
 #include <ostream>
 #include "GMSHLine.h"
 
-namespace FileIO
+namespace GeoLib
+{
+namespace IO
+{
+namespace GMSH
 {
-namespace GMSH {
 
 GMSHLine::GMSHLine(std::size_t start_point_id, std::size_t end_point_id) :
     _start_pnt_id(start_point_id), _end_pnt_id(end_point_id)
@@ -37,5 +36,6 @@ void GMSHLine::resetLineData(std::size_t start_point_id, std::size_t end_point_i
     _end_pnt_id = end_point_id;
 }
 
-}
-} // end namespace FileIO
+} // end namespace GMSH
+} // end namespace IO
+} // end namespace GeoLib
diff --git a/FileIO/GmshIO/GMSHLine.h b/GeoLib/IO/Gmsh/GMSHLine.h
similarity index 82%
rename from FileIO/GmshIO/GMSHLine.h
rename to GeoLib/IO/Gmsh/GMSHLine.h
index 939ea4b93523078bdd2f423cccc87a12a8cf3462..f6ca31d91cce46f78d18927d96bd28631a6b1932 100644
--- a/FileIO/GmshIO/GMSHLine.h
+++ b/GeoLib/IO/Gmsh/GMSHLine.h
@@ -1,8 +1,4 @@
 /**
- * \file
- * \author Thomas Fischer
- * \date   Mar 22, 2012
- * \brief  Definition of the GMSHLine class.
  *
  * \copyright
  * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
@@ -17,9 +13,12 @@
 
 #include <iosfwd>
 
-namespace FileIO
+namespace GeoLib
+{
+namespace IO
+{
+namespace GMSH
 {
-namespace GMSH {
 
 class GMSHLine {
 public:
@@ -33,7 +32,8 @@ private:
     std::size_t _end_pnt_id;
 };
 
-}
-}
+} // end namespace GMSH
+} // end namespace IO
+} // end namespace GeoLib
 
 #endif /* GMSHLINE_H_ */
diff --git a/FileIO/GmshIO/GMSHLineLoop.cpp b/GeoLib/IO/Gmsh/GMSHLineLoop.cpp
similarity index 87%
rename from FileIO/GmshIO/GMSHLineLoop.cpp
rename to GeoLib/IO/Gmsh/GMSHLineLoop.cpp
index 5a5d803c477bc1171850d27d3c644ea8d2691792..7874006c36d1ea40e8b3f22fcbaabe9a41b4ac1e 100644
--- a/FileIO/GmshIO/GMSHLineLoop.cpp
+++ b/GeoLib/IO/Gmsh/GMSHLineLoop.cpp
@@ -1,8 +1,4 @@
 /**
- * \file
- * \author Thomas Fischer
- * \date   Mar 22, 2012
- * \brief  Implementation of the GMSHLineLoop class.
  *
  * \copyright
  * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
@@ -17,9 +13,12 @@
 #include "GMSHLine.h"
 #include "GMSHLineLoop.h"
 
-namespace FileIO
+namespace GeoLib
+{
+namespace IO
+{
+namespace GMSH
 {
-namespace GMSH {
 
 GMSHLineLoop::GMSHLineLoop(bool is_sfc) :
     _is_sfc(is_sfc)
@@ -56,5 +55,6 @@ void GMSHLineLoop::write(std::ostream &os, std::size_t line_offset, std::size_t
 
 }
 
-}
-} // end namespace FileIO
+}  // end namespace GMSH
+}  // end namespace IO
+}  // end namespace GeoLib
diff --git a/FileIO/GmshIO/GMSHLineLoop.h b/GeoLib/IO/Gmsh/GMSHLineLoop.h
similarity index 84%
rename from FileIO/GmshIO/GMSHLineLoop.h
rename to GeoLib/IO/Gmsh/GMSHLineLoop.h
index b1cad96d57966726d35e2ba1d56d55fa611aa9f3..bba65e7b2f438d30a0174dd0eed37b8b2c28451f 100644
--- a/FileIO/GmshIO/GMSHLineLoop.h
+++ b/GeoLib/IO/Gmsh/GMSHLineLoop.h
@@ -1,8 +1,4 @@
 /**
- * \file
- * \author Thomas Fischer
- * \date   Mar 22, 2012
- * \brief  Definition of the GMSHLineLoop class.
  *
  * \copyright
  * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
@@ -18,10 +14,12 @@
 #include <vector>
 #include <iosfwd>
 
-
-namespace FileIO
+namespace GeoLib
+{
+namespace IO
+{
+namespace GMSH
 {
-namespace GMSH {
 
 class GMSHLine;
 
@@ -39,7 +37,8 @@ private:
     bool _is_sfc;
 };
 
-}
-}
+}  // end namespace GMSH
+}  // end namespace IO
+}  // end namespace GeoLib
 
 #endif /* GMSHLINELOOP_H_ */
diff --git a/FileIO/GmshIO/GMSHMeshDensityStrategy.h b/GeoLib/IO/Gmsh/GMSHMeshDensityStrategy.h
similarity index 81%
rename from FileIO/GmshIO/GMSHMeshDensityStrategy.h
rename to GeoLib/IO/Gmsh/GMSHMeshDensityStrategy.h
index ff908199926e116917801c09497b558a43b04da5..943eaa1d7afdb20832dc284dd1bd6cd26b020517 100644
--- a/FileIO/GmshIO/GMSHMeshDensityStrategy.h
+++ b/GeoLib/IO/Gmsh/GMSHMeshDensityStrategy.h
@@ -1,8 +1,4 @@
 /**
- * \file
- * \author Thomas Fischer
- * \date   2010-03-05
- * \brief  Definition of the GMSHMeshDensityStrategy class.
  *
  * \copyright
  * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
@@ -19,13 +15,11 @@
 
 namespace GeoLib
 {
-    class Point;
-}
-
-namespace FileIO
+class Point;
+namespace IO
+{
+namespace GMSH
 {
-namespace GMSH {
-
 /**
  * virtual base class GMSHMeshDensityStrategy for classes
  * GMSHAdaptiveMeshDensity and GMSHFixedMeshDensity.
@@ -39,8 +33,8 @@ public:
     virtual double getMeshDensityAtStation(GeoLib::Point const*const) const = 0;
 };
 
-}
-} // end namespace
-
+}  // end namespace GMSH
+}  // end namespace IO
+}  // end namespace GeoLib
 
 #endif /* GMSHMESHDENSITYSTRATEGY_H_ */
diff --git a/FileIO/GmshIO/GMSHPoint.cpp b/GeoLib/IO/Gmsh/GMSHPoint.cpp
similarity index 81%
rename from FileIO/GmshIO/GMSHPoint.cpp
rename to GeoLib/IO/Gmsh/GMSHPoint.cpp
index 1e0d13d6c47574ee36ba8a35d5031d656166bdf8..ae9714f5f98618d5dd1ffe23384f945b03c463bc 100644
--- a/FileIO/GmshIO/GMSHPoint.cpp
+++ b/GeoLib/IO/Gmsh/GMSHPoint.cpp
@@ -1,8 +1,4 @@
 /**
- * \file
- * \author Thomas Fischer
- * \date   2012-03-21
- * \brief  Implementation of the GMSHPoint class.
  *
  * \copyright
  * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
@@ -15,11 +11,14 @@
 #include <cmath>
 #include <limits>
 
-#include "GmshIO/GMSHPoint.h"
+#include "GMSHPoint.h"
 
-namespace FileIO
+namespace GeoLib
+{
+namespace IO
+{
+namespace GMSH
 {
-namespace GMSH {
 
 GMSHPoint::GMSHPoint(GeoLib::Point const& pnt, std::size_t id, double mesh_density) :
     GeoLib::Point(pnt, id), _mesh_density(mesh_density)
@@ -44,5 +43,6 @@ std::ostream& operator<< (std::ostream &os, GMSHPoint const& p)
     return os;
 }
 
-}
-} // end namespace FileIO
+}  // end namespace GMSH
+}  // end namespace IO
+}  // end namespace GeoLib
diff --git a/FileIO/GmshIO/GMSHPoint.h b/GeoLib/IO/Gmsh/GMSHPoint.h
similarity index 83%
rename from FileIO/GmshIO/GMSHPoint.h
rename to GeoLib/IO/Gmsh/GMSHPoint.h
index b2788802e8615b183079f55811115cec2c4000ff..11b2885d1a9cda36c26d2c94246a2dbed8b857a9 100644
--- a/FileIO/GmshIO/GMSHPoint.h
+++ b/GeoLib/IO/Gmsh/GMSHPoint.h
@@ -1,8 +1,4 @@
 /**
- * \file
- * \author Thomas Fischer
- * \date   2012-03-21
- * \brief  Definition of the GMSHPoint class.
  *
  * \copyright
  * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
@@ -18,9 +14,12 @@
 // GeoLib
 #include "GeoLib/Point.h"
 
-namespace FileIO
+namespace GeoLib
+{
+namespace IO
+{
+namespace GMSH
 {
-namespace GMSH {
 
 class GMSHPoint : public GeoLib::Point {
 public:
@@ -34,7 +33,8 @@ private:
 /** overload the output operator for class GMSHPoint */
 std::ostream& operator<< (std::ostream &os, GMSHPoint const& p);
 
-}
-}
+}  // end namespace GMSH
+}  // end namespace IO
+}  // end namespace GeoLib
 
 #endif /* GMSHPOINT_H_ */
diff --git a/FileIO/GmshIO/GMSHPolygonTree.cpp b/GeoLib/IO/Gmsh/GMSHPolygonTree.cpp
similarity index 98%
rename from FileIO/GmshIO/GMSHPolygonTree.cpp
rename to GeoLib/IO/Gmsh/GMSHPolygonTree.cpp
index be35d891e14795e569229e9b61081c852c508927..a33f6863d566508fc88c4c6844deee2648f3b0e5 100644
--- a/FileIO/GmshIO/GMSHPolygonTree.cpp
+++ b/GeoLib/IO/Gmsh/GMSHPolygonTree.cpp
@@ -1,8 +1,4 @@
 /**
- * \file
- * \author Thomas Fischer
- * \date   Mar 27, 2012
- * \brief  Implementation of the GMSHPolygonTree class.
  *
  * \copyright
  * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
@@ -24,9 +20,12 @@
 #include "GeoLib/PolylineWithSegmentMarker.h"
 #include "GeoLib/PolygonWithSegmentMarker.h"
 
-namespace FileIO
+namespace GeoLib
+{
+namespace IO
+{
+namespace GMSH
 {
-namespace GMSH {
 
 GMSHPolygonTree::GMSHPolygonTree(GeoLib::PolygonWithSegmentMarker* polygon,
                 GMSHPolygonTree* parent,
@@ -252,7 +251,7 @@ void GMSHPolygonTree::initMeshDensityStrategy()
     }
 }
 
-void GMSHPolygonTree::createGMSHPoints(std::vector<FileIO::GMSH::GMSHPoint*> & gmsh_pnts) const
+void GMSHPolygonTree::createGMSHPoints(std::vector<GMSHPoint*> & gmsh_pnts) const
 {
     const std::size_t n_pnts_polygon (_node_polygon->getNumberOfPoints());
     for (std::size_t k(0); k<n_pnts_polygon-1; k++) {
@@ -423,5 +422,6 @@ void GMSHPolygonTree::getStationsInsideSubPolygons(std::vector<GeoLib::Point con
     }
 }
 
-}
-} // end namespace FileIO
+}  // end namespace GMSH
+}  // end namespace IO
+}  // end namespace GeoLib
diff --git a/FileIO/GmshIO/GMSHPolygonTree.h b/GeoLib/IO/Gmsh/GMSHPolygonTree.h
similarity index 89%
rename from FileIO/GmshIO/GMSHPolygonTree.h
rename to GeoLib/IO/Gmsh/GMSHPolygonTree.h
index b234fbb64e51dfe3a1d62898d49d189efb39a6de..8b42c0bd134fed33f4c69d1ec62165c0457a9fcc 100644
--- a/FileIO/GmshIO/GMSHPolygonTree.h
+++ b/GeoLib/IO/Gmsh/GMSHPolygonTree.h
@@ -1,8 +1,4 @@
 /**
- * \file
- * \author Thomas Fischer
- * \date   Mar 27 2012
- * \brief  Definition of the GMSHPolygonTree class.
  *
  * \copyright
  * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
@@ -26,15 +22,15 @@
 
 namespace GeoLib
 {
-    class GEOObjects;
-    class Polygon;
-    class PolylineWithSegmentMarker;
-    class PolygonWithSegmentMarker;
-}
+class GEOObjects;
+class Polygon;
+class PolylineWithSegmentMarker;
+class PolygonWithSegmentMarker;
 
-namespace FileIO
+namespace IO
+{
+namespace GMSH
 {
-namespace GMSH {
 
 class GMSHPolygonTree: public GeoLib::SimplePolygonTree {
 public:
@@ -79,7 +75,7 @@ public:
      * Method creates the gmsh point data structures - including the mesh density.
      * @param gmsh_pnts a vector of pointers to instances of class GMSHPoint
      */
-    void createGMSHPoints(std::vector<FileIO::GMSH::GMSHPoint*> & gmsh_pnts) const;
+    void createGMSHPoints(std::vector<GMSHPoint*> & gmsh_pnts) const;
 
     virtual void writeLineLoop(std::size_t &line_offset, std::size_t &sfc_offset, std::ostream& out) const;
     void writeSubPolygonsAsLineConstraints(std::size_t &line_offset, std::size_t sfc_number, std::ostream& out) const;
@@ -98,12 +94,13 @@ private:
     std::string const& _geo_name;
     std::vector<GeoLib::Point const*> _stations;
     std::vector<GeoLib::PolylineWithSegmentMarker*> _plys;
-    std::vector<FileIO::GMSH::GMSHLine*> _gmsh_lines_for_constraints;
+    std::vector<GMSHLine*> _gmsh_lines_for_constraints;
 
     GMSHMeshDensityStrategy * _mesh_density_strategy;
 };
 
-}
-}
+}  // end namespace GMSH
+}  // end namespace IO
+}  // end namespace GeoLib
 
 #endif /* GMSHPOLYGONTREE_H_ */
diff --git a/MeshLib/IO/GmshReader.cpp b/MeshLib/IO/GmshReader.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9ffc22d6dadceeb750ef2ac7eb3603a2f7289b37
--- /dev/null
+++ b/MeshLib/IO/GmshReader.cpp
@@ -0,0 +1,272 @@
+/**
+ *
+ * \copyright
+ * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ */
+
+#include "GmshReader.h"
+
+#include "MeshLib/Elements/Element.h"
+#include "MeshLib/Elements/Line.h"
+#include "MeshLib/Elements/Tri.h"
+#include "MeshLib/Elements/Quad.h"
+#include "MeshLib/Elements/Tet.h"
+#include "MeshLib/Elements/Hex.h"
+#include "MeshLib/Elements/Prism.h"
+#include "MeshLib/Elements/Pyramid.h"
+
+#include "MeshLib/Node.h"
+#include "MeshLib/Mesh.h"
+
+#include "MeshLib/MeshEditing/ElementValueModification.h"
+
+#include "BaseLib/FileTools.h"
+
+#include <fstream>
+#include <map>
+#include <vector>
+
+namespace MeshLib
+{
+namespace IO
+{
+namespace GMSH
+{
+
+bool isGMSHMeshFile(const std::string& fname)
+{
+    std::ifstream input(fname.c_str());
+
+    if (!input) {
+        ERR("isGMSHMeshFile(): Could not open file %s.", fname.c_str());
+        return false;
+    }
+
+    std::string header_first_line;
+    input >> header_first_line;
+    if (header_first_line.find("$MeshFormat") != std::string::npos) {
+        // read version
+        std::string version;
+        getline(input, version);
+        getline(input, version);
+        INFO("isGMSHMeshFile(): Found GMSH mesh file version: %s.",
+             version.c_str());
+        input.close();
+        return true;
+    }
+
+    return false;
+}
+
+void readNodeIDs(std::ifstream& in, unsigned n_nodes,
+                 std::vector<unsigned>& node_ids,
+                 std::map<unsigned, unsigned> const& id_map)
+{
+    unsigned idx;
+    for (unsigned i = 0; i < n_nodes; i++)
+    {
+        in >> idx;
+        node_ids.push_back(id_map.at(idx));
+    }
+}
+
+std::pair<MeshLib::Element*, int> readElement(
+    std::ifstream& in, std::vector<MeshLib::Node*> const& nodes,
+    std::map<unsigned, unsigned> const& id_map)
+{
+    unsigned idx, type, n_tags, dummy;
+    int mat_id;
+    std::vector<unsigned> node_ids;
+    std::vector<MeshLib::Node*> elem_nodes;
+    in >> idx >> type >> n_tags >> mat_id >> dummy;
+
+    // skip tags
+    for (std::size_t j = 2; j < n_tags; j++)
+        in >> dummy;
+
+    switch (type)
+    {
+    case 1: {
+        readNodeIDs(in, 2, node_ids, id_map);
+        // edge_nodes array will be deleted from Line object
+        auto edge_nodes = new MeshLib::Node*[2];
+        edge_nodes[0] = nodes[node_ids[0]];
+        edge_nodes[1] = nodes[node_ids[1]];
+        return std::make_pair(new MeshLib::Line(edge_nodes), mat_id);
+    }
+    case 2: {
+        readNodeIDs(in, 3, node_ids, id_map);
+        auto tri_nodes = new MeshLib::Node*[3];
+        tri_nodes[0] = nodes[node_ids[2]];
+        tri_nodes[1] = nodes[node_ids[1]];
+        tri_nodes[2] = nodes[node_ids[0]];
+        return std::make_pair(new MeshLib::Tri(tri_nodes), mat_id);
+    }
+    case 3: {
+        readNodeIDs(in, 4, node_ids, id_map);
+        auto quad_nodes = new MeshLib::Node*[4];
+        for (unsigned k(0); k < 4; k++)
+            quad_nodes[k] = nodes[node_ids[k]];
+        return std::make_pair(new MeshLib::Quad(quad_nodes), mat_id);
+    }
+    case 4: {
+        readNodeIDs(in, 4, node_ids, id_map);
+        auto tet_nodes = new MeshLib::Node*[5];
+        for (unsigned k(0); k < 4; k++)
+            tet_nodes[k] = nodes[node_ids[k]];
+        return std::make_pair(new MeshLib::Tet(tet_nodes), mat_id);
+    }
+    case 5: {
+        readNodeIDs(in, 8, node_ids, id_map);
+        auto hex_nodes = new MeshLib::Node*[8];
+        for (unsigned k(0); k < 8; k++)
+            hex_nodes[k] = nodes[node_ids[k]];
+        return std::make_pair(new MeshLib::Hex(hex_nodes), mat_id);
+    }
+    case 6: {
+        readNodeIDs(in, 6, node_ids, id_map);
+        auto prism_nodes = new MeshLib::Node*[6];
+        for (unsigned k(0); k < 6; k++)
+            prism_nodes[k] = nodes[node_ids[k]];
+        return std::make_pair(new MeshLib::Prism(prism_nodes), mat_id);
+    }
+    case 7: {
+        readNodeIDs(in, 5, node_ids, id_map);
+        auto pyramid_nodes = new MeshLib::Node*[5];
+        for (unsigned k(0); k < 5; k++)
+            pyramid_nodes[k] = nodes[node_ids[k]];
+        return std::make_pair(new MeshLib::Pyramid(pyramid_nodes), mat_id);
+    }
+    case 15:
+        in >> dummy; // skip rest of line
+        break;
+    default:
+        WARN("readGMSHMesh(): Unknown element type %d.", type);
+        break;
+    }
+    return std::make_pair(nullptr, -1);
+}
+
+MeshLib::Mesh* readGMSHMesh(std::string const& fname)
+{
+    std::string line;
+    std::ifstream in(fname.c_str(), std::ios::in);
+    if (!in.is_open())
+    {
+        WARN ("readGMSHMesh() - Could not open file %s.", fname.c_str());
+        return nullptr;
+    }
+
+    getline(in, line); // $MeshFormat keyword
+    if (line.find("$MeshFormat") == std::string::npos)
+    {
+        in.close();
+        WARN ("No GMSH file format recognized.");
+        return nullptr;
+    }
+
+    getline(in, line); // version-number file-type data-size
+    if (line.substr(0,3).compare("2.2") != 0) {
+        WARN("Wrong gmsh file format version.");
+        return nullptr;
+    }
+
+    if (line.substr(4,1).compare("0") != 0) {
+        WARN("Currently reading gmsh binary file type is not supported.");
+        return nullptr;
+    }
+    getline(in, line); //$EndMeshFormat
+
+    std::vector<MeshLib::Node*> nodes;
+    std::vector<MeshLib::Element*> elements;
+    std::vector<int> materials;
+    std::map<unsigned, unsigned> id_map;
+    while (line.find("$EndElements") == std::string::npos)
+    {
+        // Node data
+        getline(in, line); //$Nodes Keywords
+        if (line.find("$Nodes") != std::string::npos)
+        {
+            std::size_t n_nodes(0);
+            long id;
+            double x, y, z;
+            in >> n_nodes >> std::ws;
+            nodes.resize(n_nodes);
+            for (std::size_t i = 0; i < n_nodes; i++) {
+                in >> id >> x >> y >> z >> std::ws;
+                id_map.insert(std::map<unsigned, unsigned>::value_type(id, i));
+                nodes[i] = new MeshLib::Node(x,y,z,id);
+            }
+            getline(in, line); // End Node keyword $EndNodes
+        }
+
+        // Element data
+        if (line.find("$Elements") != std::string::npos)
+        {
+            std::size_t n_elements(0);
+            if (! (in >> n_elements >> std::ws)) { // number-of-elements
+                ERR("Read GMSH mesh does not contain any elements");
+            }
+            elements.reserve(n_elements);
+            materials.reserve(n_elements);
+            for (std::size_t i = 0; i < n_elements; i++)
+            {
+                MeshLib::Element* elem(nullptr);
+                int mat_id(0);
+                std::tie(elem, mat_id) = readElement(in, nodes, id_map);
+
+                if (elem) {
+                    elements.push_back(elem);
+                    materials.push_back(mat_id);
+                }
+            }
+            getline(in, line); // END keyword
+        }
+
+        if (line.find("PhysicalNames") != std::string::npos)
+        {
+            std::size_t n_lines(0);
+            in >> n_lines >> std::ws; // number-of-lines
+            for (std::size_t i = 0; i < n_lines; i++)
+                getline(in, line);
+            getline(in, line); // END keyword
+        }
+    }
+    in.close();
+    if (elements.empty()) {
+        for (auto it(nodes.begin()); it != nodes.end(); ++it) {
+            delete *it;
+        }
+        return nullptr;
+    }
+
+    MeshLib::Mesh * mesh(new MeshLib::Mesh(
+        BaseLib::extractBaseNameWithoutExtension(fname), nodes, elements));
+
+    boost::optional<MeshLib::PropertyVector<int> &> opt_material_ids(
+        mesh->getProperties().createNewPropertyVector<int>(
+            "MaterialIDs", MeshLib::MeshItemType::Cell, 1)
+    );
+    if (!opt_material_ids) {
+        WARN("Could not create PropertyVector for MaterialIDs in Mesh.");
+    } else {
+        MeshLib::PropertyVector<int> & material_ids(opt_material_ids.get());
+        material_ids.insert(material_ids.end(), materials.cbegin(),
+            materials.cend());
+    }
+
+    MeshLib::ElementValueModification::condense(*mesh);
+
+    INFO("\t... finished.");
+    INFO("Nr. Nodes: %d.", nodes.size());
+    INFO("Nr. Elements: %d.", elements.size());
+
+    return mesh;
+}
+
+} // end namespace GMSH
+} // end namespace IO
+} // end namespace MeshLib
diff --git a/MeshLib/IO/GmshReader.h b/MeshLib/IO/GmshReader.h
new file mode 100644
index 0000000000000000000000000000000000000000..f2a58d07480e7a036d444af36fe908c79a840c6f
--- /dev/null
+++ b/MeshLib/IO/GmshReader.h
@@ -0,0 +1,38 @@
+/**
+ *
+ * \copyright
+ * Copyright (c) 2012-2016, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ */
+
+#include <string>
+
+namespace MeshLib
+{
+class Mesh;
+
+namespace IO
+{
+namespace GMSH
+{
+
+/**
+ * checks if there is a GMSH mesh file header
+ * @param fname the file name of the mesh (including the path)
+ * @return true, if the file seems to be a valid GMSH file, else false
+ */
+bool isGMSHMeshFile(const std::string& fname);
+
+/**
+ * reads a mesh created by GMSH - this implementation is based on the former
+ * function GMSH2MSH
+ * @param fname the file name of the mesh (including the path)
+ * @return
+ */
+MeshLib::Mesh* readGMSHMesh(std::string const& fname);
+
+} // end namespace GMSH
+} // end namespace IO
+} // end namespace MeshLib