diff --git a/Applications/DataExplorer/DataView/MeshElementRemovalDialog.cpp b/Applications/DataExplorer/DataView/MeshElementRemovalDialog.cpp
index dd8cc1c32569b19d6119cd8f7b4e758c9343e2d3..688b50882266f3dd1b2a5f198130230d06db762e 100644
--- a/Applications/DataExplorer/DataView/MeshElementRemovalDialog.cpp
+++ b/Applications/DataExplorer/DataView/MeshElementRemovalDialog.cpp
@@ -74,7 +74,7 @@ void MeshElementRemovalDialog::accept()
 	{
 		QList<QListWidgetItem*> items = this->materialListWidget->selectedItems();
 		for (int i=0; i<items.size(); ++i)
-			ex.searchByMaterialID(items[i]->text().toInt());
+			ex.searchByPropertyValue(items[i]->text().toInt());
 		anything_checked = true;
 	}
 	if (this->boundingBoxCheckBox->isChecked())
diff --git a/Applications/Utils/MeshEdit/removeMeshElements.cpp b/Applications/Utils/MeshEdit/removeMeshElements.cpp
index 05b42215517f97d53626a5605e2aedea3d169db0..3d3dc01d9af622b6640e00034195d240a664b444 100644
--- a/Applications/Utils/MeshEdit/removeMeshElements.cpp
+++ b/Applications/Utils/MeshEdit/removeMeshElements.cpp
@@ -11,35 +11,44 @@
  *              http://www.opengeosys.org/LICENSE.txt
  */
 
+#include <memory>
+
 // TCLAP
 #include "tclap/CmdLine.h"
 
-// ThirdParty/logog
-#include "logog/include/logog.hpp"
-
-// BaseLib
-#include "LogogSimpleFormatter.h"
+#include "Applications/ApplicationsLib/LogogSetup.h"
 
-// FileIO
-#include "Legacy/MeshIO.h"
-#include "readMeshFromFile.h"
+#include "FileIO/readMeshFromFile.h"
+#include "FileIO/writeMeshToFile.h"
 
-// MeshLib
-#include "Mesh.h"
+#include "MeshLib/Mesh.h"
 #include "MeshLib/Node.h"
-#include "Elements/Element.h"
-#include "MeshEnums.h"
-#include "MeshSearch/ElementSearch.h"
-#include "MeshEditing/RemoveMeshComponents.h"
+#include "MeshLib/Elements/Element.h"
+#include "MeshLib/MeshEnums.h"
+#include "MeshLib/MeshSearch/ElementSearch.h"
+#include "MeshLib/MeshEditing/RemoveMeshComponents.h"
+
+template <typename PROPERTY_TYPE>
+void searchByProperty(std::string const& property_name,
+                      std::vector<PROPERTY_TYPE> const& property_values,
+                      MeshLib::ElementSearch& searcher)
+{
+	for (auto const& property_value : property_values) {
+		const std::size_t n_marked_elements =
+		    searcher.searchByPropertyValue(property_value, property_name);
+		INFO("%d elements with property value %s found.", n_marked_elements,
+		     std::to_string(property_value).c_str());
+	}
+}
 
 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);
+	ApplicationsLib::LogogSetup logog_setup;
 
-	TCLAP::CmdLine cmd("Remove mesh elements.", ' ', "0.1");
+	TCLAP::CmdLine cmd(
+	    "Remove mesh elements. The documentation is available at "
+	    "https://docs.opengeosys.org/docs/tools/meshing/remove-mesh-elements.",
+	    ' ', "0.1");
 
 	// Bounding box params
 	TCLAP::ValueArg<double> zLargeArg("", "z-max", "largest allowed extent in z-dimension",
@@ -67,9 +76,15 @@ int main (int argc, char* argv[])
 	TCLAP::MultiArg<std::string> eleTypeArg("t", "element-type",
 	                                      "element type to be removed", false, "element type");
 	cmd.add(eleTypeArg);
-	TCLAP::MultiArg<unsigned> matIDArg("m", "material-id",
-	                                      "material id", false, "material id");
-	cmd.add(matIDArg);
+
+	TCLAP::MultiArg<int> int_property_arg("", "int-property-value",
+	                                      "new property value (data type int)",
+	                                      false, "number");
+	cmd.add(int_property_arg);
+	TCLAP::ValueArg<std::string> property_name_arg(
+	    "n", "property-name", "name of property in the mesh", false,
+	    "MaterialIDs", "string");
+	cmd.add(property_name_arg);
 
 	// I/O params
 	TCLAP::ValueArg<std::string> mesh_out("o", "mesh-output-file",
@@ -83,13 +98,14 @@ int main (int argc, char* argv[])
 
 	cmd.parse(argc, argv);
 
-	MeshLib::Mesh const*const mesh (FileIO::readMeshFromFile(mesh_in.getValue()));
+	std::unique_ptr<MeshLib::Mesh const> mesh(
+	    FileIO::readMeshFromFile(mesh_in.getValue()));
 	INFO("Mesh read: %d nodes, %d elements.", mesh->getNNodes(), mesh->getNElements());
-	MeshLib::ElementSearch ex(*mesh);
+	MeshLib::ElementSearch searcher(*mesh);
 
 	// search elements IDs to be removed
 	if (zveArg.isSet()) {
-		const std::size_t n_removed_elements = ex.searchByContent();
+		const std::size_t n_removed_elements = searcher.searchByContent();
 		INFO("%d zero volume elements found.", n_removed_elements);
 	}
 	if (eleTypeArg.isSet()) {
@@ -97,16 +113,14 @@ int main (int argc, char* argv[])
 		for (auto typeName : eleTypeNames) {
 			const MeshLib::MeshElemType type = MeshLib::String2MeshElemType(typeName);
 			if (type == MeshLib::MeshElemType::INVALID) continue;
-			const std::size_t n_removed_elements = ex.searchByElementType(type);
+			const std::size_t n_removed_elements = searcher.searchByElementType(type);
 			INFO("%d %s elements found.", n_removed_elements, typeName.c_str());
 		}
 	}
-	if (matIDArg.isSet()) {
-		const std::vector<unsigned> vec_matID = matIDArg.getValue();
-		for (auto matID : vec_matID) {
-			const std::size_t n_removed_elements = ex.searchByMaterialID(matID);
-			INFO("%d elements with material ID %d found.", n_removed_elements, matID);
-		}
+
+	if (int_property_arg.isSet()) {
+		searchByProperty(property_name_arg.getValue(),
+		                 int_property_arg.getValue(), searcher);
 	}
 
 	if (xSmallArg.isSet() || xLargeArg.isSet() ||
@@ -130,31 +144,26 @@ int main (int argc, char* argv[])
 		    aabb_error = true;
 		}
 		if (aabb_error)
-		    return 1;
+		    return EXIT_FAILURE;
 
 		std::array<MathLib::Point3d, 2> extent({{
 			MathLib::Point3d(std::array<double,3>{{xSmallArg.getValue(),
 				ySmallArg.getValue(), zSmallArg.getValue()}}),
 			MathLib::Point3d(std::array<double,3>{{xLargeArg.getValue(),
 				yLargeArg.getValue(), zLargeArg.getValue()}})}});
-		const std::size_t n_removed_elements = ex.searchByBoundingBox(
+		const std::size_t n_removed_elements = searcher.searchByBoundingBox(
 			GeoLib::AABB(extent.begin(), extent.end()));
 		INFO("%d elements found.", n_removed_elements);
 	}
 
 	// remove the elements and create a new mesh object.
-	MeshLib::Mesh const*const new_mesh = MeshLib::removeElements(*mesh, ex.getSearchedElementIDs(), mesh->getName());
+	std::unique_ptr<MeshLib::Mesh const> new_mesh(MeshLib::removeElements(
+	    *mesh, searcher.getSearchedElementIDs(), mesh->getName()));
 
 	// write into a file
-	FileIO::Legacy::MeshIO meshIO;
-	meshIO.setMesh(new_mesh);
-	meshIO.writeToFile(mesh_out.getValue());
-
-	delete custom_format;
-	delete logog_cout;
-	LOGOG_SHUTDOWN();
+	FileIO::writeMeshToFile(*new_mesh, mesh_out.getValue());
 
-	return 0;
+	return EXIT_SUCCESS;
 }
 
 
diff --git a/MeshLib/MeshSearch/ElementSearch.cpp b/MeshLib/MeshSearch/ElementSearch.cpp
index 8a035b8b15a35418efb6702f90b86e07d7600100..f8d30092812a372b52566b60e9f9940cfb61bf06 100644
--- a/MeshLib/MeshSearch/ElementSearch.cpp
+++ b/MeshLib/MeshSearch/ElementSearch.cpp
@@ -11,7 +11,6 @@
 
 #include <logog/include/logog.hpp>
 
-#include "MeshLib/Mesh.h"
 #include "MeshLib/Node.h"
 #include "MeshLib/Elements/Element.h"
 
@@ -22,26 +21,6 @@ ElementSearch::ElementSearch(const MeshLib::Mesh &mesh)
 {
 }
 
-std::size_t ElementSearch::searchByMaterialID(int const matID)
-{
-	boost::optional<MeshLib::PropertyVector<int> const&> opt_pv(
-		this->_mesh.getProperties().getPropertyVector<int>("MaterialIDs")
-	);
-	if (!opt_pv)
-		return 0;
-
-	MeshLib::PropertyVector<int> const& pv(opt_pv.get());
-
-	std::vector<std::size_t> matchedIDs;
-	for (std::size_t i(0); i<pv.getNumberOfTuples(); ++i) {
-		if (pv[i]==matID)
-			matchedIDs.push_back(i);
-	}
-
-	this->updateUnion(matchedIDs);
-	return matchedIDs.size();
-}
-
 template <typename Container, typename Predicate>
 std::vector<std::size_t> filter(Container const& container, Predicate const& p)
 {
diff --git a/MeshLib/MeshSearch/ElementSearch.h b/MeshLib/MeshSearch/ElementSearch.h
index db26a7e8756771ad73b6332744c0606946db61d2..98e38e60cfd458949aa49072a8473faaddc10b13 100644
--- a/MeshLib/MeshSearch/ElementSearch.h
+++ b/MeshLib/MeshSearch/ElementSearch.h
@@ -14,6 +14,7 @@
 #include <vector>
 
 #include "GeoLib/AABB.h"
+#include "MeshLib/Mesh.h"
 #include "MeshLib/MeshEnums.h"
 
 namespace MeshLib {
@@ -31,8 +32,46 @@ public:
 	/// return marked elements
 	const std::vector<std::size_t>& getSearchedElementIDs() const { return _marked_elements; }
 
-	/// Marks all elements with the given Material ID.
-	std::size_t searchByMaterialID(int const matID);
+	/// @tparam PROPERTY_TYPE integral type of the property
+	/// Different properties can be assigned to the elements of the mesh. These
+	/// properties can be accessed by the name of the property. The method marks
+	/// all elements of the mesh for the property \c property_name with the
+	/// given property value \c property_value.
+	/// @param property_value the value of the property the elements have to
+	/// have to be marked
+	/// @param property_name the name of the property the searching/marking is
+	/// based on
+	/// @return The number of marked elements will be returned. The concrete
+	/// element ids can be requested by getSearchedElementIDs().
+	template <typename PROPERTY_TYPE>
+	std::size_t searchByPropertyValue(
+	    PROPERTY_TYPE const property_value,
+	    std::string const& property_name = "MaterialIDs")
+	{
+		boost::optional<MeshLib::PropertyVector<PROPERTY_TYPE> const&> opt_pv(
+		    _mesh.getProperties().getPropertyVector<PROPERTY_TYPE>(
+		        property_name));
+		if (!opt_pv) {
+			WARN("Property \"%s\" not found in mesh.", property_name.c_str());
+			return 0;
+		}
+
+		MeshLib::PropertyVector<PROPERTY_TYPE> const& pv(opt_pv.get());
+		if (pv.getMeshItemType() != MeshLib::MeshItemType::Cell) {
+			WARN("The property \"%s\" is not assigned to mesh elements.",
+			     property_name.c_str());
+			return 0;
+		}
+
+		std::vector<std::size_t> matchedIDs;
+		for (std::size_t i(0); i < pv.getNumberOfTuples(); ++i) {
+			if (pv[i] == property_value)
+				matchedIDs.push_back(i);
+		}
+
+		updateUnion(matchedIDs);
+		return matchedIDs.size();
+	}
 
 	/// Marks all elements of the given element type.
 	std::size_t searchByElementType(MeshElemType eleType);