diff --git a/Applications/Utils/MeshEdit/CMakeLists.txt b/Applications/Utils/MeshEdit/CMakeLists.txt
index c222040502c1654fb9461f669a386cf947a14857..d3649ee77f3c2cd256ebd172e9a1d25b1004befe 100644
--- a/Applications/Utils/MeshEdit/CMakeLists.txt
+++ b/Applications/Utils/MeshEdit/CMakeLists.txt
@@ -103,3 +103,18 @@ ADD_CATALYST_DEPENDENCY(checkMesh)
 
 SET_TARGET_PROPERTIES(checkMesh
 	PROPERTIES FOLDER Utilities)
+
+ADD_EXECUTABLE( reviseMesh reviseMesh.cpp)
+TARGET_LINK_LIBRARIES ( reviseMesh
+	BaseLib
+	FileIO
+	MathLib
+	MeshLib
+	InSituLib
+	${CATALYST_LIBRARIES}
+)
+ADD_CATALYST_DEPENDENCY(reviseMesh)
+
+SET_TARGET_PROPERTIES(reviseMesh
+	PROPERTIES FOLDER Utilities)
+	
\ No newline at end of file
diff --git a/Applications/Utils/MeshEdit/editMaterialID.cpp b/Applications/Utils/MeshEdit/editMaterialID.cpp
index 1503253f177c9eab613d1c902c016f071fcaf1c0..5ba436ab1d8213633aa33b331916aef1fde32cf7 100644
--- a/Applications/Utils/MeshEdit/editMaterialID.cpp
+++ b/Applications/Utils/MeshEdit/editMaterialID.cpp
@@ -13,16 +13,17 @@
 #include "logog/include/logog.hpp"
 
 // BaseLib
-#include "LogogSimpleFormatter.h"
+#include "BaseLib/LogogSimpleFormatter.h"
 
 // FileIO
-#include "Legacy/MeshIO.h"
-#include "readMeshFromFile.h"
+#include "FileIO/Legacy/MeshIO.h"
+#include "FileIO/readMeshFromFile.h"
+#include "FileIO/writeMeshToFile.h"
 
 // MeshLib
-#include "Mesh.h"
-#include "Elements/Element.h"
-#include "MeshEditing/ElementValueModification.h"
+#include "MeshLib/Mesh.h"
+#include "MeshLib/Elements/Element.h"
+#include "MeshLib/MeshEditing/ElementValueModification.h"
 
 int main (int argc, char* argv[])
 {
@@ -34,7 +35,12 @@ int main (int argc, char* argv[])
 	TCLAP::CmdLine cmd("Edit material IDs of mesh elements.", ' ', "0.1");
 	TCLAP::SwitchArg replaceArg("r", "replace", "replace material IDs", false);
 	TCLAP::SwitchArg condenseArg("c", "condense", "condense material IDs", false);
-	cmd.xorAdd(replaceArg, condenseArg);
+	TCLAP::SwitchArg specifyArg("s", "specify", "specify material IDs by element types (-e)", false);
+	std::vector<TCLAP::Arg*> vec_xors;
+	vec_xors.push_back(&replaceArg);
+	vec_xors.push_back(&condenseArg);
+	vec_xors.push_back(&specifyArg);
+	cmd.xorAdd(vec_xors);
 	TCLAP::ValueArg<std::string> mesh_in("i", "mesh-input-file",
 	                                     "the name of the file containing the input mesh", true,
 	                                     "", "file name");
@@ -49,17 +55,28 @@ int main (int argc, char* argv[])
 	TCLAP::ValueArg<unsigned> newIDArg("n", "new-material-id",
 	                                      "new material id", false, 0, "number");
 	cmd.add(newIDArg);
+	std::vector<std::string> eleList(getMeshElemTypeStringsShort());
+	TCLAP::ValuesConstraint<std::string> allowedVals(eleList);
+	TCLAP::ValueArg<std::string> eleTypeArg("e", "element-type",
+	                                      "element type", false, "", &allowedVals);
+	cmd.add(eleTypeArg);
+
 	cmd.parse(argc, argv);
 
-	if (!replaceArg.isSet() && !condenseArg.isSet()) {
-		INFO("Please select editing mode: -r or -c");
+	if (!replaceArg.isSet() && !condenseArg.isSet() && !specifyArg.isSet()) {
+		INFO("Please select editing mode: -r or -c or -s");
 		return 0;
 	} else if (replaceArg.isSet() && condenseArg.isSet()) {
-		INFO("Please select only one editing mode: -r or -c");
+		INFO("Please select only one editing mode: -r or -c or -s");
 		return 0;
 	} else if (replaceArg.isSet()) {
 		if (!matIDArg.isSet() || !newIDArg.isSet()) {
-			INFO("current and new material IDs must be provided for relplacement");
+			INFO("current and new material IDs must be provided for replacement");
+			return 0;
+		}
+	} else if (specifyArg.isSet()) {
+		if (!eleTypeArg.isSet() || !newIDArg.isSet()) {
+			INFO("element type and new material IDs must be provided to specify elements");
 			return 0;
 		}
 	}
@@ -78,12 +95,17 @@ int main (int argc, char* argv[])
 			INFO("%d -> %d", oldID, newID);
 			MeshLib::ElementValueModification::replace(*mesh, oldID, newID, true);
 		}
+	} else if (specifyArg.isSet()) {
+		INFO("Specifying material ID...");
+		const std::string eleTypeName(eleTypeArg.getValue());
+		const MeshElemType eleType = String2MeshElemType(eleTypeName);
+		const unsigned newID = newIDArg.getValue();
+		unsigned cnt = MeshLib::ElementValueModification::setByElementType(*mesh, eleType, newID);
+		INFO("updated %d elements", cnt);
 	}
 
 	// write into a file
-	FileIO::Legacy::MeshIO meshIO;
-	meshIO.setMesh(mesh);
-	meshIO.writeToFile(mesh_out.getValue());
+	FileIO::writeMeshToFile(*mesh, mesh_out.getValue());
 
 	delete custom_format;
 	delete logog_cout;
diff --git a/Applications/Utils/MeshEdit/reviseMesh.cpp b/Applications/Utils/MeshEdit/reviseMesh.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7dc04e72d1a9e73fc95a1fedce9fdfe9beb72ac9
--- /dev/null
+++ b/Applications/Utils/MeshEdit/reviseMesh.cpp
@@ -0,0 +1,80 @@
+/**
+ * @copyright
+ * Copyright (c) 2012-2014, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/LICENSE.txt
+ *
+ */
+
+#include <array>
+#include <string>
+
+#include "logog/include/logog.hpp"
+#include "tclap/CmdLine.h"
+
+#include "BaseLib/BuildInfo.h"
+#include "BaseLib/StringTools.h"
+#include "BaseLib/LogogSimpleFormatter.h"
+#include "BaseLib/FileTools.h"
+
+#include "MeshLib/Node.h"
+#include "MeshLib/Elements/Element.h"
+#include "MeshLib/Mesh.h"
+#include "MeshLib/MeshEditing/MeshRevision.h"
+
+#include "FileIO/readMeshFromFile.h"
+#include "FileIO/writeMeshToFile.h"
+
+int main(int argc, char *argv[])
+{
+	LOGOG_INITIALIZE();
+	logog::Cout* logog_cout (new logog::Cout);
+	BaseLib::LogogSimpleFormatter *custom_format (new BaseLib::LogogSimpleFormatter);
+	logog_cout->SetFormatter(*custom_format);
+
+	TCLAP::CmdLine cmd("Mesh revision tool", ' ', BaseLib::BuildInfo::git_version_sha1);
+	TCLAP::ValueArg<std::string> input_arg("i", "input-mesh-file","input mesh file",true,"","string");
+	cmd.add( input_arg );
+	TCLAP::ValueArg<std::string> output_arg("o", "output-mesh-file","output mesh file",true,"","string");
+	cmd.add( output_arg );
+	TCLAP::SwitchArg simplify_arg("s","simplify","simplify the mesh (removing duplicated nodes)");
+	cmd.add( simplify_arg );
+	TCLAP::ValueArg<double> eps_arg("e", "eps","Minimum distance for nodes not to be collapsed",
+									false, std::numeric_limits<double>::epsilon(),"float");
+	cmd.add( eps_arg );
+	TCLAP::ValueArg<unsigned> minDim_arg("d", "min-ele-dim","Minimum dimension of elements to be inserted into new mesh",
+									false, 1, "unsigned");
+	cmd.add( minDim_arg );
+	cmd.parse( argc, argv );
+
+	// read a mesh file
+	MeshLib::Mesh* org_mesh (FileIO::readMeshFromFile(input_arg.getValue()));
+	if (!org_mesh)
+		return 0;
+	INFO("Mesh read: %d nodes, %d elements.", org_mesh->getNNodes(), org_mesh->getNElements());
+
+	// revise the mesh
+	MeshLib::Mesh* new_mesh = nullptr;
+	if (simplify_arg.getValue()) {
+		INFO("Simplifying the mesh...");
+		MeshLib::MeshRevision rev(const_cast<MeshLib::Mesh&>(*org_mesh));
+		unsigned int minDim = (minDim_arg.isSet() ? minDim_arg.getValue() : org_mesh->getDimension());
+		new_mesh = rev.simplifyMesh("revised_mesh", eps_arg.getValue(), minDim);
+	}
+
+	// write into a file
+	if (new_mesh) {
+		INFO("Revised mesh: %d nodes, %d elements.", new_mesh->getNNodes(), new_mesh->getNElements());
+		FileIO::writeMeshToFile(*new_mesh, output_arg.getValue());
+	}
+
+	delete org_mesh;
+	delete new_mesh;
+
+	delete custom_format;
+	delete logog_cout;
+	LOGOG_SHUTDOWN();
+
+	return 0;
+}
diff --git a/FileIO/CMakeLists.txt b/FileIO/CMakeLists.txt
index 6c9d6c4b9856763fb6ece580b00a3110bf86227e..0f4f665edb519c41b16942e77fad22227eddead3 100644
--- a/FileIO/CMakeLists.txt
+++ b/FileIO/CMakeLists.txt
@@ -19,6 +19,8 @@ SET( SOURCES
 	TINInterface.cpp
 	Writer.h
 	Writer.cpp
+	writeMeshToFile.h
+	writeMeshToFile.cpp
 )
 
 GET_SOURCE_FILES(SOURCES_LEGACY Legacy)
diff --git a/FileIO/writeMeshToFile.cpp b/FileIO/writeMeshToFile.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..730e7faa5874d735e0df306f24f88d46a7a98011
--- /dev/null
+++ b/FileIO/writeMeshToFile.cpp
@@ -0,0 +1,42 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2014, 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 "writeMeshToFile.h"
+
+// ThirdParty/logog
+#include "logog/include/logog.hpp"
+
+// BaseLib
+#include "FileTools.h"
+#include "StringTools.h"
+
+// MeshLib
+#include "Mesh.h"
+
+// FileIO
+#include "Legacy/MeshIO.h"
+#include "FileIO/VtkIO/VtuInterface.h"
+
+namespace FileIO
+{
+void writeMeshToFile(const MeshLib::Mesh &mesh, const std::string &file_name)
+{
+	if (BaseLib::hasFileExtension("msh", file_name))
+	{
+		Legacy::MeshIO meshIO;
+		meshIO.setMesh(&mesh);
+		meshIO.writeToFile(file_name);
+	} else if (BaseLib::hasFileExtension("vtu", file_name)) {
+		FileIO::VtuInterface writer(&mesh);
+		writer.writeToFile(file_name);
+	} else {
+		ERR("writeMeshToFile(): Unknown mesh file format in file %s.", file_name.c_str());
+	}
+}
+
+} // end namespace FileIO
diff --git a/FileIO/writeMeshToFile.h b/FileIO/writeMeshToFile.h
new file mode 100644
index 0000000000000000000000000000000000000000..bab68d434ddb88a7f1d00fbf7126c61557dfcda2
--- /dev/null
+++ b/FileIO/writeMeshToFile.h
@@ -0,0 +1,24 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2014, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ */
+
+#ifndef WRITEMESHTOFILE_H_
+#define WRITEMESHTOFILE_H_
+
+#include <string>
+
+namespace MeshLib
+{
+class Mesh;
+}
+
+namespace FileIO
+{
+void writeMeshToFile(const MeshLib::Mesh &mesh, const std::string &file_name);
+}
+
+#endif // WRITEMESHTOFILE_H_
diff --git a/MeshLib/MeshEditing/ElementValueModification.cpp b/MeshLib/MeshEditing/ElementValueModification.cpp
index 092cc2f7cc594eb585f0b085b0f97a8d7fbb5740..a9219f686814552e3264d282c8010c9db2d76f3c 100644
--- a/MeshLib/MeshEditing/ElementValueModification.cpp
+++ b/MeshLib/MeshEditing/ElementValueModification.cpp
@@ -66,7 +66,7 @@ bool ElementValueModification::replace(MeshLib::Mesh &mesh, unsigned old_value,
 		}
 	}
 	const std::size_t nElements (mesh.getNElements());
-	std::vector<MeshLib::Element*> elements (mesh.getElements());
+	std::vector<MeshLib::Element*> &elements (const_cast<std::vector<MeshLib::Element*>&>(mesh.getElements()));
 	for (unsigned i=0; i<nElements; ++i)
 	{
 		if (elements[i]->getValue() == old_value)
@@ -84,11 +84,25 @@ unsigned ElementValueModification::condense(MeshLib::Mesh &mesh)
 		reverse_mapping[value_mapping[i]] = i;
 
 	const std::size_t nElements (mesh.getNElements());
-	std::vector<MeshLib::Element*> elements (mesh.getElements());
+	std::vector<MeshLib::Element*> &elements (const_cast<std::vector<MeshLib::Element*>&>(mesh.getElements()));
 	for (unsigned i=0; i<nElements; ++i)
 		elements[i]->setValue(reverse_mapping[elements[i]->getValue()]);
 
 	return nValues;
 }
 
+unsigned ElementValueModification::setByElementType(MeshLib::Mesh &mesh, MeshElemType ele_type, unsigned new_value)
+{
+	std::vector<MeshLib::Element*> &elements (const_cast<std::vector<MeshLib::Element*>&>(mesh.getElements()));
+	unsigned nValues = 0;
+	for (auto e : elements) {
+		if (e->getGeomType()!=ele_type)
+			continue;
+		e->setValue(new_value);
+		nValues++;
+	}
+
+	return nValues;
+}
+
 } // end namespace MeshLib
diff --git a/MeshLib/MeshEditing/ElementValueModification.h b/MeshLib/MeshEditing/ElementValueModification.h
index 472fff8eead45aa616a6da08228880a477200f98..6d1b43744f05d950f26ae11b5710274aa2446cb0 100644
--- a/MeshLib/MeshEditing/ElementValueModification.h
+++ b/MeshLib/MeshEditing/ElementValueModification.h
@@ -17,6 +17,8 @@
 
 #include <vector>
 
+#include "MeshLib/MeshEnums.h"
+
 namespace MeshLib {
 // forward declarations
 class Mesh;
@@ -35,6 +37,10 @@ public:
 	/// Returns true if successful or false if the value is already taken.
 	static bool replace(MeshLib::Mesh &mesh, unsigned old_value, unsigned new_value, bool replace_if_exists = false);
 
+	/// Sets new value for all elements having the given element type
+	/// Returns the number of elements having the given element type
+	static unsigned setByElementType(MeshLib::Mesh &mesh, MeshElemType ele_type, unsigned new_value);
+
 private:
 	/// Returns the values of elements within the mesh
 	static std::vector<unsigned> getMeshValues(const MeshLib::Mesh &mesh);
diff --git a/MeshLib/MeshEnums.cpp b/MeshLib/MeshEnums.cpp
index 8eb465b4c0378a79d8eb17885472ec144c4e195e..00167b95a96473d02f2a9f923ab2290ce40d89b0 100644
--- a/MeshLib/MeshEnums.cpp
+++ b/MeshLib/MeshEnums.cpp
@@ -33,6 +33,25 @@ const std::string MeshElemType2String(const MeshElemType t)
 	return "none";
 }
 
+const std::string MeshElemType2StringShort(const MeshElemType t)
+{
+	if (t == MeshElemType::LINE)
+		return "line";
+	if (t == MeshElemType::QUAD)
+		return "quad";
+	if (t == MeshElemType::HEXAHEDRON)
+		return "hex";
+	if (t == MeshElemType::TRIANGLE)
+		return "tri";
+	if (t == MeshElemType::TETRAHEDRON)
+		return "tet";
+	if (t == MeshElemType::PRISM)
+		return "pris";
+	if (t == MeshElemType::PYRAMID)
+		return "pyra";
+	return "none";
+}
+
 MeshElemType String2MeshElemType(const std::string &s)
 {
 	if ((s.compare("line") == 0) || (s.compare("Line") == 0))
@@ -52,6 +71,27 @@ MeshElemType String2MeshElemType(const std::string &s)
 	return MeshElemType::INVALID;
 }
 
+std::vector<MeshElemType> getMeshElemTypes()
+{
+	std::vector<MeshElemType> vec;
+	vec.push_back(MeshElemType::LINE);
+	vec.push_back(MeshElemType::QUAD);
+	vec.push_back(MeshElemType::HEXAHEDRON);
+	vec.push_back(MeshElemType::TRIANGLE);
+	vec.push_back(MeshElemType::TETRAHEDRON);
+	vec.push_back(MeshElemType::PRISM);
+	vec.push_back(MeshElemType::PYRAMID);
+	return vec;
+}
+
+std::vector<std::string> getMeshElemTypeStringsShort()
+{
+	std::vector<std::string> vec;
+	for (MeshElemType eleType : getMeshElemTypes())
+		vec.push_back(MeshElemType2StringShort(eleType));
+	return vec;
+}
+
 const std::string MeshQualityType2String(const MeshQualityType t)
 {
     if (t == MeshQualityType::AREA)
diff --git a/MeshLib/MeshEnums.h b/MeshLib/MeshEnums.h
index 22611565816375063881257a21ae84045aee11fa..d616776c878cb94d86046eed5f9d4cab729a900d 100644
--- a/MeshLib/MeshEnums.h
+++ b/MeshLib/MeshEnums.h
@@ -16,6 +16,7 @@
 #define MESHENUMS_H
 
 #include <string>
+#include <vector>
 
 /**
  * \brief Types of mesh elements supported by OpenGeoSys.
@@ -73,9 +74,18 @@ enum class MeshQualityType
 /// Given a MeshElemType this returns the appropriate string.
 const std::string MeshElemType2String(const MeshElemType t);
 
+/// Given a MeshElemType this returns the appropriate string with a short name.
+const std::string MeshElemType2StringShort(const MeshElemType t);
+
 /// Given a string of the shortened name of the element type, this returns the corresponding MeshElemType.
 MeshElemType String2MeshElemType(const std::string &s);
 
+/// Returns a vector of all mesh element types
+std::vector<MeshElemType> getMeshElemTypes();
+
+/// Returns a vector of strings of mesh element types
+std::vector<std::string> getMeshElemTypeStringsShort();
+
 const std::string MeshQualityType2String(const MeshQualityType t);
 
 #endif //MESHENUMS_H