diff --git a/AneuMeshLoader.cpp b/AneuMeshLoader.cpp new file mode 100644 index 0000000000000000000000000000000000000000..54ef3be28c8b81a28db7ce66b383a1b3b53980c6 --- /dev/null +++ b/AneuMeshLoader.cpp @@ -0,0 +1,51 @@ +#include +#include + +#include "AneuMeshLoader.h" +#include "Exception.h" + + +void AneuMeshLoader::loadMesh(const string& filename) { + std::ifstream file(filename); + if (!file) { + throw Wrong_file_format(); + } + cout << "file " << filename << " has opened" << endl; + + int cnt, dim; + file >> cnt >> dim; + nodes.reserve(cnt); + for (size_t i = 1; i <= cnt; i++) { + size_t id = i; + std::vector coord(dim); + for (size_t j = 1; j <= dim; j++) { + file >> coord[j - 1]; + } + nodes.emplace_back(id, coord, true); + } + file >> cnt >> dim; + for (int i = 1; i <= cnt; i++) { + size_t id = i; + std::vector coord(dim); + size_t materialId; + file >> materialId; + for (int j = 1; j <= dim; ++j) { + file >> coord[j - 1]; + } + finiteElements.emplace_back(id, materialId, coord); + } + + file >> cnt >> dim; + for (int i = 1; i <= cnt; i++) { + size_t id = i; + std::vector coord(dim); + size_t materialId; + file >> materialId; + for (int j = 1; j <= dim; j++) { + file >> coord[j - 1]; + } + boundaryFiniteElements.emplace_back(id, materialId, coord); + } + file.close(); + std::cout << ".aneu file downloaded" << std::endl; +} diff --git a/AneuMeshLoader.h b/AneuMeshLoader.h new file mode 100644 index 0000000000000000000000000000000000000000..4971ad2094f503bd04c33ad0aa45134fceb722fd --- /dev/null +++ b/AneuMeshLoader.h @@ -0,0 +1,14 @@ +#pragma once +#include + +#include "MeshLoader.h" +#include "Structure.h" + +using std::cin; +using std::cout; +using std::endl; + +class AneuMeshLoader : public MeshLoader { +public: + void loadMesh(const string&) override; +}; \ No newline at end of file diff --git a/Exception.h b/Exception.h new file mode 100644 index 0000000000000000000000000000000000000000..f829a690f812396dfb48a86582d2b311b1adb689 --- /dev/null +++ b/Exception.h @@ -0,0 +1,31 @@ +#pragma once +#include +#include + +class File_not_found : public std::exception { + std::string err; +public: + File_not_found() { + err.assign("Error : unable to open file"); + } + explicit File_not_found(const std::string& file) { + err.assign("Error: Unable to open " + file + " file"); + } + const char* what() const noexcept override { + return err.c_str(); + } +}; + +class Wrong_file_format : public std::exception { + std::string err; +public: + Wrong_file_format() { + err.assign("Error : inappropriate file format"); + } + explicit Wrong_file_format(const std::string& file_format) { + err.assign("Error : Format " + file_format + " is unsuitable"); + } + const char* what() const noexcept override { + return err.c_str(); + } +}; diff --git a/MeshLoader.cpp b/MeshLoader.cpp new file mode 100644 index 0000000000000000000000000000000000000000..740a81c83b0615f30c48c491d79ff0dc3a581231 --- /dev/null +++ b/MeshLoader.cpp @@ -0,0 +1,173 @@ +#include "MeshLoader.h" + +std::vector& MeshLoader::GetNodes() { + return nodes; +} + +std::vector& MeshLoader::GetFE() { + return finiteElements; +} + +std::vector& MeshLoader::GetBFE() { + return boundaryFiniteElements; +} + +std::vector MeshLoader::findFE(size_t id_1, size_t id_2, size_t id_3) { + std::vector res; + auto iter = finiteElements.begin(); + auto end_iter = finiteElements.end(); + + while (iter != end_iter) { + iter = std::find_if(iter, end_iter, + [id_1, id_2, id_3](const FiniteElement& elem) { + return std::find(elem.material.begin(), elem.material.end(), id_1) != elem.material.end() + && std::find(elem.material.begin(), elem.material.end(), id_2) != elem.material.end() + && std::find(elem.material.begin(), elem.material.end(), id_3) != elem.material.end(); + }); + if (iter != end_iter) { + res.push_back(iter->ID); + iter++; + } + } + return res; +} + +std::vector MeshLoader::findEdge(size_t id_1, size_t id_2) { + std::vector res; + auto iter = finiteElements.begin(); + auto end_iter = finiteElements.end(); + + while (iter != end_iter) { + iter = std::find_if(iter, end_iter, [id_1, id_2](FiniteElement& elem) { + return std::find(elem.material.begin(), elem.material.end(), id_1) != elem.material.end() + && std::find(elem.material.begin(), elem.material.end(), id_2) != elem.material.end(); + }); + if (iter != end_iter) { + res.push_back(*iter); + iter++; + } + } + return res; +} + +std::vector MeshLoader::vertex_node_by_id(size_t id) { + std::set res; + auto iter = boundaryFiniteElements.begin(); + while (iter != boundaryFiniteElements.end()) { + iter = std::find_if(iter, boundaryFiniteElements.end(), [id](const BoundaryFiniteElement& s) { return s.ID_surface == id; }); + if (iter != boundaryFiniteElements.end()) + { + for (const auto& elem : iter->node_boundary) { + res.insert(get_node_by_id(id)); + } + ++iter; + } + } + return std::vector(res.begin(), res.end()); +} + +std::vector MeshLoader::get_material_id(size_t id) { + std::list res; + auto elem_by_material = nodes.begin(); + auto last_elem = nodes.end(); + while (elem_by_material != last_elem) { + + elem_by_material = std::find_if(elem_by_material, last_elem, [id](const Node& v) { return v.ID_node == id; }); + + if (elem_by_material != last_elem) { + res.push_back(*elem_by_material); + ++elem_by_material; + } + } + return std::vector(res.begin(), res.end()); + +} + +std::vector> MeshLoader::get_close_nodes() { + std::vector> res(nodes.size()); + for (const auto& iter_FiniteElement : boundaryFiniteElements) + { + for (auto& iter_nodes : iter_FiniteElement.node_boundary) + { + res[iter_nodes - 1].insert(iter_FiniteElement.node_boundary.begin(), iter_FiniteElement.node_boundary.end()); + res[iter_nodes - 1].erase(iter_nodes); + } + } + return res; +} + +std::vector MeshLoader::get_BoundaryFinite_id(size_t id) { + std::list res; + auto surface_by_ID = boundaryFiniteElements.begin(); + auto last_elem = boundaryFiniteElements.end(); + while (surface_by_ID != last_elem) { + surface_by_ID = std::find_if(surface_by_ID, last_elem, [id](const BoundaryFiniteElement& v) { return v.ID_surface == id; }); + if (surface_by_ID != last_elem) { + res.push_back(*surface_by_ID); + ++surface_by_ID; + } + } + return std::vector(res.begin(), res.end()); + +} + +Node MeshLoader::get_node(size_t id) { + nodes.at(id); +} + +Node& MeshLoader::get_node_by_id(size_t id) { + return nodes[id]; +} + +void MeshLoader::Print() { + cout << &GetNodes() << endl << &GetFE() << endl << &GetBFE << endl; +} + +void MeshLoader::insert_node() { + std::unordered_set edge; + for (auto& elem : boundaryFiniteElements) + { + std::vector iter(elem.ID_boundary); + for (auto i = iter.begin(); i != iter.end(); i++) + { + for (auto j = i + 1; j != iter.end(); j++) + { + Edge current_edge(*i, *j); + auto find_edge = edge.find(current_edge); + if (find_edge == edge.end()) { + Node left_node = get_node_by_id(elem.node_boundary[*i]); + Node right_node = get_node_by_id(elem.node_boundary[*j]); + std::vector x = { (left_node.coord[0] + right_node.coord[0]) / 2, + (left_node.coord[0] + right_node.coord[0]) / 2, + (left_node.coord[0] + right_node.coord[0]) / 2 }; + Node center_node(nodes.size() + 1, x, false); + current_edge.self_id = nodes.size() + 1; + edge.insert(current_edge); + nodes.push_back(std::move(center_node)); + elem.node_boundary.emplace_back(current_edge.self_id); + } + else { + elem.node_boundary.emplace_back(find_edge->self_id); + } + + } + } + } + for (auto& it : boundaryFiniteElements) + { + std::vector current_iter(it.node_boundary); + for (auto i = current_iter.begin(); i != current_iter.end() - 1; i++) + { + for (auto j = i + 1; j != current_iter.end(); j++) + { + Edge search_edge(*i, *j); + auto search_point = edge.find(search_edge); + if (search_point != edge.end()) + { + it.node_boundary.emplace_back(search_point->self_id); + } + } + } + } +} + diff --git a/MeshLoader.h b/MeshLoader.h new file mode 100644 index 0000000000000000000000000000000000000000..f4ddbde00958fe800902bca6839a3fa9ca49375f --- /dev/null +++ b/MeshLoader.h @@ -0,0 +1,39 @@ +#pragma once +#include +#include +#include +#include +#include + +#include "Structure.h" + +using std::cin; +using std::cout; +using std::endl; +using std::string; + +class MeshLoader { +protected: + std::vector nodes; + std::vector finiteElements; + std::vector boundaryFiniteElements; +public: + virtual void loadMesh(const string&) = 0; + virtual ~MeshLoader() = default; + + std::vector& GetNodes(); + std::vector& GetFE(); + std::vector& GetBFE(); + std::vector findFE(size_t, size_t, size_t); + std::vector findEdge(size_t, size_t); + std::vector vertex_node_by_id(size_t); + std::vector> get_close_nodes(); + std::vector get_material_id(size_t); + std::vector get_BoundaryFinite_id(size_t); + Node get_node(size_t); + Node& get_node_by_id(size_t); + + void Print(); + void insert_node(); + +}; diff --git a/Structure.cpp b/Structure.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d6ea493a1667acfe59f3731dbd35e9c394f3e6d5 --- /dev/null +++ b/Structure.cpp @@ -0,0 +1,45 @@ +#include "Structure.h" + +std::ostream& operator << (std::ostream& out, const Node& elem) { + out << elem.ID_node << " | "; + for (auto& tmp : elem.coord) + out << tmp << " "; + out << " | " << elem.flag << " | " << std::endl; + return out; +} + +std::ostream& operator<<(std::ostream& out, const FiniteElement& elem) { + out << elem.ID << " | " << elem.ID_material << " | "; + for (auto& tmp : elem.material) + out << tmp << " "; + out << " | " << std::endl; + return out; +} + +std::ostream& operator<< (std::ostream& out, const BoundaryFiniteElement& elem) { + out << elem.ID_boundary << " | " << elem.ID_surface << " | "; + for (auto& tmp : elem.node_boundary) + out << tmp << " "; + out << " | " << std::endl; + return out; +} + +bool Edge::operator == (const Edge& p) const { + return (head_id == p.head_id && tail_id == p.tail_id) || + (head_id == p.tail_id && tail_id == p.head_id); +} + + + +void HashEdge::hash_combine(size_t& seed, const size_t& val) const { + seed ^= std::hash()(val) + 0x9e3779b9 + (seed << 6) + (seed >> 2); +} + +size_t HashEdge::operator()(const Edge& p) const { + size_t seed = 0; + hash_combine(seed, p.head_id); + hash_combine(seed, p.tail_id); + hash_combine(seed, p.self_id); + + return seed; +} \ No newline at end of file diff --git a/Structure.h b/Structure.h new file mode 100644 index 0000000000000000000000000000000000000000..142d01be031a4c8b50c0ef8c900dfac281107b9d --- /dev/null +++ b/Structure.h @@ -0,0 +1,59 @@ +#pragma once + +#include +#include + +struct Node { + size_t ID_node; + std::vector coord; + bool flag; + + Node(size_t p_ID_node, std::vector p_coord, bool p_flag) : + ID_node(p_ID_node), + coord(std::move(p_coord)), + flag(p_flag) {}; + friend std::ostream& operator << (std::ostream& out, const Node& elem); + +}; + +struct FiniteElement { + size_t ID, ID_material; + std::vector material; + + FiniteElement(size_t p_ID, size_t p_ID_material, std::vector p_materual) : + ID(p_ID), + ID_material(p_ID), + material(std::move(p_materual)) {}; + + friend std::ostream& operator << (std::ostream& out, const FiniteElement& elem); +}; + +struct BoundaryFiniteElement { + size_t ID_boundary, ID_surface; + std::vector node_boundary; + + BoundaryFiniteElement(size_t p_ID_boundary, size_t p_ID_surface, std::vectorp_node_boundary) : + ID_boundary(p_ID_boundary), + ID_surface(p_ID_surface), + node_boundary(std::move(p_node_boundary)) {}; + + friend std::ostream& operator << (std::ostream& out, const BoundaryFiniteElement& elem); +}; + +struct Edge { + size_t head_id; + size_t tail_id; + size_t self_id; + Edge() = default; + Edge(size_t p_head_id, size_t p_tail_id) : + head_id(p_head_id), + tail_id(p_tail_id) {}; + + bool operator == (const Edge& p) const; +}; + +struct HashEdge { + void hash_combine(size_t& seed, const size_t& val) const; + std::size_t operator() (const Edge& p) const; + +}; diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a4cb99f235cb30727e2d722b66235ca7ef2032c9 --- /dev/null +++ b/main.cpp @@ -0,0 +1,47 @@ +#include +#include +#include +#include +#include + +#include "AneuMeshLoader.h" + +int main() { + const std::string name = "myfile"; + std::vector node; + MeshLoader* load = new AneuMeshLoader; + std::vector elem; + std::vector FEelem; + std::vector> close; + std::vector surface; + + load->loadMesh(name); + std::cout << "TEST" << std::endl; + + std::cout << "find finite element" << std::endl; + elem = load->findFE(3, 2, 2); + std::cout << elem << std::endl; + elem.clear(); + + std::cout << "findEdge" << std::endl; + FEelem = load->findEdge(1, 2); + for (const auto& x : FEelem) + std::cout << x << std::endl; + FEelem.clear(); + + std::cout << "get vertex node by id" << std::endl; + node = load->vertex_node_by_id(1); + std::cout << node << std::endl; + node.clear(); + + std::cout << "get boundary finite id" << std::endl; + surface = load->get_BoundaryFinite_id(1); + std::cout << surface << std::endl; + surface.clear(); + + std::cout << "Insert nodes" << std::endl; + load->insert_node(); + load->Print(); + delete(load); + return 0; +}