diff --git a/MeshLib/MeshSurfaceExtraction.cpp b/MeshLib/MeshSurfaceExtraction.cpp index 1d208018dd7ac44ac5f4370647a6bf369e8cef5b..4fca3dd9733c6babe1f02815f952c753aa63512f 100644 --- a/MeshLib/MeshSurfaceExtraction.cpp +++ b/MeshLib/MeshSurfaceExtraction.cpp @@ -14,13 +14,12 @@ #include "MeshSurfaceExtraction.h" -#include <memory> - #include <boost/math/constants/constants.hpp> - #include <logog/include/logog.hpp> +#include <memory> #include "MeshLib/Elements/Line.h" +#include "MeshLib/Elements/Point.h" #include "MeshLib/Elements/Quad.h" #include "MeshLib/Elements/Tri.h" #include "MeshLib/Mesh.h" @@ -365,6 +364,9 @@ std::vector<MeshLib::Element*> MeshSurfaceExtraction::createSfcElementVector( case MeshElemType::QUAD: new_elements.push_back(new MeshLib::Quad(new_nodes)); break; + case MeshElemType::LINE: + new_elements.push_back(new MeshLib::Line(new_nodes)); + break; default: OGS_FATAL( "MeshSurfaceExtraction::createSfcElementVector Unknown " @@ -435,4 +437,143 @@ bool MeshSurfaceExtraction::createSfcMeshProperties( return true; } +std::unique_ptr<MeshLib::Mesh> getBoundaryElementsAsMesh( + MeshLib::Mesh const& bulk_mesh, + std::string const& subsfc_node_id_prop_name, + std::string const& subsfc_element_id_prop_name, + std::string const& face_id_prop_name) +{ + auto const mesh_dimension = bulk_mesh.getDimension(); + if (mesh_dimension < 2 || mesh_dimension > 3) + { + ERR("Cannot handle meshes of dimension %i", mesh_dimension); + } + + std::vector<std::size_t> element_to_bulk_element_id_map; + std::vector<std::size_t> element_to_bulk_face_id_map; + std::vector<MeshLib::Element*> sfc_elements; + auto const& bulk_elements = bulk_mesh.getElements(); + for (auto const* elem : bulk_elements) + { + const unsigned element_dimension(elem->getDimension()); + if (element_dimension < mesh_dimension) + { + continue; + } + + if (!elem->isBoundaryElement()) + { + continue; + } + + const unsigned nFaces(elem->getNumberOfFaces()); + for (unsigned j = 0; j < nFaces; ++j) + { + if (elem->getNeighbor(j) != nullptr) + { + continue; + } + + auto const face = + std::unique_ptr<MeshLib::Element const>{elem->getFace(j)}; + switch (face->getGeomType()) + { + case MeshElemType::TRIANGLE: + { + sfc_elements.push_back(new MeshLib::Tri( + *static_cast<const MeshLib::Tri*>(face.get()))); + break; + } + case MeshElemType::QUAD: + { + sfc_elements.push_back(new MeshLib::Quad( + *static_cast<const MeshLib::Quad*>(face.get()))); + break; + } + case MeshElemType::LINE: + { + sfc_elements.push_back(new MeshLib::Line( + *static_cast<const MeshLib::Line*>(face.get()))); + break; + } + case MeshElemType::POINT: + { + sfc_elements.push_back(new MeshLib::Point( + *static_cast<const MeshLib::Point*>(face.get()))); + break; + } + default: + ERR("Unknown face element extracted."); + } + element_to_bulk_element_id_map.push_back(elem->getID()); + element_to_bulk_face_id_map.push_back(j); + } + } + + std::vector<MeshLib::Node*> sfc_nodes; + std::vector<std::size_t> node_id_map(bulk_mesh.getNumberOfNodes()); + MeshSurfaceExtraction::get2DSurfaceNodes( + sfc_nodes, bulk_mesh.getNumberOfNodes(), sfc_elements, node_id_map); + + // create new elements vector with newly created nodes (and delete + // temp-elements) + std::vector<MeshLib::Element*> new_elements; + try + { + new_elements = MeshSurfaceExtraction::createSfcElementVector( + sfc_elements, sfc_nodes, node_id_map); + } + catch (std::runtime_error const& err) + { + ERR("BoundaryExtraction; could not create new surface elements:\n%s.", + err.what()); + std::for_each(sfc_elements.begin(), sfc_elements.end(), + [](MeshLib::Element* e) { delete e; }); + std::for_each(sfc_nodes.begin(), sfc_nodes.end(), + [](MeshLib::Node* n) { delete n; }); + return nullptr; + } + std::for_each(sfc_elements.begin(), sfc_elements.end(), + [](MeshLib::Element* e) { delete e; }); + + std::vector<std::size_t> id_map; + id_map.reserve(sfc_nodes.size()); + std::transform(begin(sfc_nodes), end(sfc_nodes), std::back_inserter(id_map), + [](MeshLib::Node* const n) { return n->getID(); }); + std::unique_ptr<MeshLib::Mesh> surface_mesh( + new Mesh(bulk_mesh.getName() + "-Surface", sfc_nodes, new_elements)); + + // transmit the original node ids of the bulk mesh as a property + if (!subsfc_node_id_prop_name.empty()) + { + MeshLib::addPropertyToMesh(*surface_mesh, subsfc_node_id_prop_name, + MeshLib::MeshItemType::Node, 1, id_map); + } + + // transmit the original bulk element ids as a property + if (!subsfc_element_id_prop_name.empty()) + { + MeshLib::addPropertyToMesh(*surface_mesh, subsfc_element_id_prop_name, + MeshLib::MeshItemType::Cell, 1, + element_to_bulk_element_id_map); + } + + // transmit the face id of the original bulk element as a property + if (!face_id_prop_name.empty()) + { + MeshLib::addPropertyToMesh(*surface_mesh, face_id_prop_name, + MeshLib::MeshItemType::Cell, 1, + element_to_bulk_face_id_map); + } + + /// Copies relevant parts of scalar arrays to the surface mesh + if (!MeshSurfaceExtraction::createSfcMeshProperties( + *surface_mesh, bulk_mesh.getProperties(), id_map, + element_to_bulk_element_id_map)) + { + ERR("Transferring subsurface properties failed."); + } + return surface_mesh; +} + } // end namespace MeshLib diff --git a/MeshLib/MeshSurfaceExtraction.h b/MeshLib/MeshSurfaceExtraction.h index ed33b121b5735fc7c829930a0c36d665584ad961..00e0f74080ecef87d9847d2195dc0b0511303ff6 100644 --- a/MeshLib/MeshSurfaceExtraction.h +++ b/MeshLib/MeshSurfaceExtraction.h @@ -80,7 +80,6 @@ public: */ static MeshLib::Mesh* getMeshBoundary(const MeshLib::Mesh& mesh); -private: /// Functionality needed for getSurfaceNodes() and getMeshSurface() static void get2DSurfaceElements( const std::vector<MeshLib::Element*>& all_elements, @@ -136,4 +135,10 @@ private: std::vector<std::size_t> const& element_ids_map); }; -} // end namespace MeshLib +std::unique_ptr<MeshLib::Mesh> getBoundaryElementsAsMesh( + MeshLib::Mesh const& bulk_mesh, + std::string const& subsfc_node_id_prop_name, + std::string const& subsfc_element_id_prop_name, + std::string const& face_id_prop_name); + +} // namespace MeshLib