/******************************************************** * ██████╗ ██████╗████████╗██╗ * ██╔════╝ ██╔════╝╚══██╔══╝██║ * ██║ ███╗██║ ██║ ██║ * ██║ ██║██║ ██║ ██║ * ╚██████╔╝╚██████╗ ██║ ███████╗ * ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝ * Geophysical Computational Tools & Library (GCTL) * * Copyright (c) 2023 Yi Zhang (yizhang-geo@zju.edu.cn) * * GCTL is distributed under a dual licensing scheme. You can redistribute * it and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, either version 2 * of the License, or (at your option) any later version. You should have * received a copy of the GNU Lesser General Public License along with this * program. If not, see . * * If the terms and conditions of the LGPL v.2. would prevent you from using * the GCTL, please consider the option to obtain a commercial license for a * fee. These licenses are offered by the GCTL's original author. As a rule, * licenses are provided "as-is", unlimited in time for a one time fee. Please * send corresponding requests to: yizhang-geo@zju.edu.cn. Please do not forget * to include some description of your company and the realm of its activities. * Also add information on how to contact you by electronic and paper mail. ******************************************************/ #ifndef _GCTL_GMSH_IO_H #define _GCTL_GMSH_IO_H // library's head files #include "../core.h" #include "../geometry.h" #include "../utility.h" #ifdef GCTL_EIGEN #include "Eigen/Dense" #endif // GCTL_EIGEN namespace gctl { struct gmsh_physical_group { size_t dim_tag, phys_tag; std::string name; }; /** * @brief Gmsh文件的IO类,主要为调用下面定义的全局函数 */ class gmshio { public: gmshio(); gmshio(std::string filename, file_direction_e f_direct); virtual ~gmshio(); void init_file(std::string filename, file_direction_e f_direct); void reset_file(std::string filename, file_direction_e f_direct); void set_packed(index_packed_e is_packed, file_direction_e f_direct); bool initialized(file_direction_e f_direct); void read_physical_groups(array &phy_groups); void save_physical_groups(const array &phy_groups); int physical_name2tag(const array &phy_groups, std::string name); template void read_node(array> &out_nodes); template void read_node(array> &out_nodes); template void read_element(array> &out_elements, const array> &nodes, _2i_vector *ele_tag = nullptr); template void read_element(array> &out_elements, const array> &nodes, _2i_vector *ele_tag = nullptr); template void read_element(array> &out_elements, const array> &nodes, _2i_vector *ele_tag = nullptr); template void read_element(array> &out_elements, const array> &nodes, _2i_vector *ele_tag = nullptr); template void read_element(array> &out_elements, const array> &nodes, _2i_vector *ele_tag = nullptr); template void read_element(array> &out_elements, const array> &nodes, _2i_vector *ele_tag = nullptr); template void read_element(array> &out_elements, const array> &nodes, _2i_vector *ele_tag = nullptr); template void read_element(array> &out_elements, const array> &nodes, _2i_vector *ele_tag = nullptr); template void read_element(array> &out_elements, const array> &nodes, _2i_vector *ele_tag = nullptr); template void read_element(array> &out_elements, const array> &nodes, _2i_vector *ele_tag = nullptr); template void read_element(array> &out_elements, const array> &nodes, _2i_vector *ele_tag = nullptr); template void read_mesh(array> &out_elements, array> &nodes, _2i_vector *ele_tag = nullptr); template void read_mesh(array> &out_elements, array> &nodes, _2i_vector *ele_tag = nullptr); template void read_mesh(array> &out_elements, array> &nodes, _2i_vector *ele_tag = nullptr); template void read_mesh(array> &out_elements, array> &nodes, _2i_vector *ele_tag = nullptr); template void read_mesh(array> &out_elements, array> &nodes, _2i_vector *ele_tag = nullptr); template void read_mesh(array> &out_elements, array> &nodes, _2i_vector *ele_tag = nullptr); template void read_mesh(array> &out_elements, array> &nodes, _2i_vector *ele_tag = nullptr); template void read_mesh(array> &out_elements, array> &nodes, _2i_vector *ele_tag = nullptr); template void read_mesh(array> &out_elements, array> &nodes, _2i_vector *ele_tag = nullptr); template void read_mesh(array> &out_elements, array> &nodes, _2i_vector *ele_tag = nullptr); template void read_data(array &out_data, std::string data_name = ""); template void read_data(array &out_data, array &out_index, std::string data_name = ""); template void read_data(std::vector > &out_data, std::vector &out_name, mesh_data_type_e d_type, std::vector > *out_index = nullptr); template void save_mesh(const array> &element, const array> &node); template void save_mesh(const array> &element, const array> &node); template void save_mesh(const array> &element, const array> &node); template void save_mesh(const array> &element, const array> &node, array *out_ele_tag = nullptr, array *out_node_tag = nullptr); template void save_mesh(const array> &element, const array> &node, array *output_tag = nullptr); template void save_mesh(const array> &element, const array> &node); template void save_mesh(const array> &element, const array> &node); template void save_mesh(const array> &element, const array> &node); template void save_mesh(const array> &element); template void save_data(std::string dataname, const T *in_data, size_t in_size, mesh_data_type_e datatype, const size_t *in_index = nullptr); template void save_data(std::string dataname, const array &in_data, mesh_data_type_e datatype, const array *in_index = nullptr); template void save_data(std::string dataname, const std::vector &in_data, mesh_data_type_e datatype, const std::vector *in_index = nullptr); template void save_data(std::string dataname, const array> &in_data, mesh_data_type_e datatype, const array *in_index = nullptr); template void save_data(std::string dataname, const std::vector> &in_data, mesh_data_type_e datatype, const std::vector *in_index = nullptr); #ifdef GCTL_EIGEN template void save_data(std::string dataname, const Eigen::Matrix &in_data, mesh_data_type_e datatype, const Eigen::Matrix *in_index = nullptr); #endif // GCTL_EIGEN template void element_register(const array> &element, const _2i_matrix *tag_ptr = nullptr, array *rgst_index = nullptr); template void element_register(const array> &element, const _2i_matrix *tag_ptr = nullptr, array *rgst_index = nullptr); template void element_register(const array> &element, const _2i_matrix *tag_ptr = nullptr, array *rgst_index = nullptr); template void element_register(const array> &element, const _2i_matrix *tag_ptr = nullptr, array *rgst_index = nullptr); template void element_register(const array> &element, const _2i_matrix *tag_ptr = nullptr, array *rgst_index = nullptr); template void element_register(const array> &element, const _2i_matrix *tag_ptr = nullptr, array *rgst_index = nullptr); template void element_register(const array> &element, const _2i_matrix *tag_ptr = nullptr, array *rgst_index = nullptr); template void element_register(const array> &element, const _2i_matrix *tag_ptr = nullptr, array *rgst_index = nullptr); template void element_register(const array> &element, const _2i_matrix *tag_ptr = nullptr, array *rgst_index = nullptr); template void save_registered_mesh(const array> &node, array *phys_ptr = nullptr); template void save_registered_mesh(const array> &node, array *phys_ptr = nullptr); protected: std::ifstream gmsh_in; // Input stream std::ofstream gmsh_out; // Output stream index_packed_e in_packed, out_packed; // Whether the input/output node indexes are starting from zero std::vector > rgst_elem; // registered elements }; template void gmshio::read_node(array> &out_nodes) { initialized(Input); read_gmsh_node(gmsh_in, out_nodes, in_packed); return; } template void gmshio::read_node(array> &out_nodes) { initialized(Input); read_gmsh_node(gmsh_in, out_nodes, in_packed); return; } template void gmshio::read_element(array> &out_elements, const array> &nodes, _2i_vector *ele_tag) { initialized(Input); read_gmsh_element(gmsh_in, out_elements, nodes, in_packed, ele_tag); return; } template void gmshio::read_element(array> &out_elements, const array> &nodes, _2i_vector *ele_tag) { initialized(Input); read_gmsh_element(gmsh_in, out_elements, nodes, in_packed, ele_tag); return; } template void gmshio::read_element(array> &out_elements, const array> &nodes, _2i_vector *ele_tag) { initialized(Input); read_gmsh_element(gmsh_in, out_elements, nodes, in_packed, ele_tag); return; } template void gmshio::read_element(array> &out_elements, const array> &nodes, _2i_vector *ele_tag) { initialized(Input); read_gmsh_element(gmsh_in, out_elements, nodes, in_packed, ele_tag); return; } template void gmshio::read_element(array> &out_elements, const array> &nodes, _2i_vector *ele_tag) { initialized(Input); read_gmsh_element(gmsh_in, out_elements, nodes, in_packed, ele_tag); return; } template void gmshio::read_element(array> &out_elements, const array> &nodes, _2i_vector *ele_tag) { initialized(Input); read_gmsh_element(gmsh_in, out_elements, nodes, in_packed, ele_tag); return; } template void gmshio::read_element(array> &out_elements, const array> &nodes, _2i_vector *ele_tag) { initialized(Input); read_gmsh_element(gmsh_in, out_elements, nodes, in_packed, ele_tag); return; } template void gmshio::read_element(array> &out_elements, const array> &nodes, _2i_vector *ele_tag) { initialized(Input); read_gmsh_element(gmsh_in, out_elements, nodes, in_packed, ele_tag); return; } template void gmshio::read_element(array> &out_elements, const array> &nodes, _2i_vector *ele_tag) { initialized(Input); read_gmsh_element(gmsh_in, out_elements, nodes, in_packed, ele_tag); return; } template void gmshio::read_element(array> &out_elements, const array> &nodes, _2i_vector *ele_tag) { initialized(Input); read_gmsh_element(gmsh_in, out_elements, nodes, in_packed, ele_tag); return; } template void gmshio::read_element(array> &out_elements, const array> &nodes, _2i_vector *ele_tag) { initialized(Input); read_gmsh_element(gmsh_in, out_elements, nodes, in_packed, ele_tag); return; } template void gmshio::read_mesh(array> &out_elements, array> &nodes, _2i_vector *ele_tag) { read_node(nodes); read_element(out_elements, nodes, ele_tag); return; } template void gmshio::read_mesh(array> &out_elements, array> &nodes, _2i_vector *ele_tag) { read_node(nodes); read_element(out_elements, nodes, ele_tag); return; } template void gmshio::read_mesh(array> &out_elements, array> &nodes, _2i_vector *ele_tag) { read_node(nodes); read_element(out_elements, nodes, ele_tag); return; } template void gmshio::read_mesh(array> &out_elements, array> &nodes, _2i_vector *ele_tag) { read_node(nodes); read_element(out_elements, nodes, ele_tag); return; } template void gmshio::read_mesh(array> &out_elements, array> &nodes, _2i_vector *ele_tag) { read_node(nodes); read_element(out_elements, nodes, ele_tag); return; } template void gmshio::read_mesh(array> &out_elements, array> &nodes, _2i_vector *ele_tag) { read_node(nodes); read_element(out_elements, nodes, ele_tag); return; } template void gmshio::read_mesh(array> &out_elements, array> &nodes, _2i_vector *ele_tag) { read_node(nodes); read_element(out_elements, nodes, ele_tag); return; } template void gmshio::read_mesh(array> &out_elements, array> &nodes, _2i_vector *ele_tag) { read_node(nodes); read_element(out_elements, nodes, ele_tag); return; } template void gmshio::read_mesh(array> &out_elements, array> &nodes, _2i_vector *ele_tag) { read_node(nodes); read_element(out_elements, nodes, ele_tag); return; } template void gmshio::read_mesh(array> &out_elements, array> &nodes, _2i_vector *ele_tag) { read_node(nodes); read_element(out_elements, nodes, ele_tag); return; } template void gmshio::read_data(array &out_data, std::string data_name) { initialized(Input); read_gmsh_data(gmsh_in, out_data, data_name); return; } template void gmshio::read_data(array &out_data, array &out_index, std::string data_name) { initialized(Input); read_gmsh_data(gmsh_in, out_data, out_index, data_name, in_packed); return; } template void gmshio::read_data(std::vector > &out_data, std::vector &out_name, mesh_data_type_e d_type, std::vector > *out_index) { initialized(Input); read_gmsh_data(gmsh_in, out_data, out_name, d_type, out_index, in_packed); return; } template void gmshio::save_mesh(const array> &element, const array> &node) { initialized(Output); save2gmsh(gmsh_out, element, node, out_packed); return; } template void gmshio::save_mesh(const array> &element, const array> &node) { initialized(Output); save2gmsh(gmsh_out, element, node, out_packed); return; } template void gmshio::save_mesh(const array> &element, const array> &node) { initialized(Output); save2gmsh(gmsh_out, element, node, out_packed); return; } template void gmshio::save_mesh(const array> &element, const array> &node, array *out_ele_tag, array *out_node_tag) { initialized(Output); save2gmsh(gmsh_out, element, node, out_packed, out_ele_tag, out_node_tag); return; } template void gmshio::save_mesh(const array> &element, const array> &node, array *output_tag) { initialized(Output); save2gmsh(gmsh_out, element, node, out_packed, output_tag); return; } template void gmshio::save_mesh(const array> &element, const array> &node) { initialized(Output); save2gmsh(gmsh_out, element, node, out_packed); return; } template void gmshio::save_mesh(const array> &element, const array> &node) { initialized(Output); save2gmsh(gmsh_out, element, node, out_packed); return; } template void gmshio::save_mesh(const array> &element, const array> &node) { initialized(Output); save2gmsh(gmsh_out, element, node, out_packed); return; } template void gmshio::save_mesh(const array> &element) { initialized(Output); save2gmsh(gmsh_out, element, out_packed); return; } template void gmshio::save_data(std::string dataname, const T *in_data, size_t in_size, mesh_data_type_e datatype, const size_t *in_index) { initialized(Output); save_gmsh_data(gmsh_out, dataname, in_data, in_size, datatype, out_packed, in_index); return; } template void gmshio::save_data(std::string dataname, const array &in_data, mesh_data_type_e datatype, const array *in_index) { initialized(Output); save_gmsh_data(gmsh_out, dataname, in_data, datatype, out_packed, in_index); return; } template void gmshio::save_data(std::string dataname, const std::vector &in_data, mesh_data_type_e datatype, const std::vector *in_index) { initialized(Output); save_gmsh_data(gmsh_out, dataname, in_data, datatype, out_packed, in_index); return; } template void gmshio::save_data(std::string dataname, const array> &in_data, mesh_data_type_e datatype, const array *in_index) { initialized(Output); save_gmsh_data(gmsh_out, dataname, in_data, datatype, out_packed, in_index); return; } template void gmshio::save_data(std::string dataname, const std::vector> &in_data, mesh_data_type_e datatype, const std::vector *in_index) { initialized(Output); save_gmsh_data(gmsh_out, dataname, in_data, datatype, out_packed, in_index); return; } #ifdef GCTL_EIGEN template void gmshio::save_data(std::string dataname, const Eigen::Matrix &in_data, mesh_data_type_e datatype, const Eigen::Matrix *in_index) { initialized(Output); save_gmsh_data(gmsh_out, dataname, in_data, datatype, out_packed, in_index); return; } #endif // GCTL_EIGEN template void gmshio::element_register(const array> &element, const _2i_matrix *tag_ptr, array *rgst_index) { if (tag_ptr != nullptr && tag_ptr->row_size() != element.size()) { throw runtime_error("Tag size doesn't match with the element size. From gctl::gmshio::element_register(...)"); } if (rgst_index != nullptr) rgst_index->resize(element.size()); rgst_elem.reserve(rgst_elem.size() + element.size()); std::vector tmp_elem; if (tag_ptr != nullptr) { size_t c_size = tag_ptr->col_size(); tmp_elem.resize(5 + c_size); tmp_elem[0] = 2; tmp_elem[1] = c_size; for (size_t i = 0; i < element.size(); i++) { for (size_t j = 0; j < c_size; j++) { tmp_elem[j+2] = tag_ptr->at(i, j); } for (size_t j = 0; j < 3; j++) { tmp_elem[j+2+c_size] = element[i].vert[j]->id; if (out_packed == NotPacked) tmp_elem[j+2+c_size] += 1; } if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size(); rgst_elem.push_back(tmp_elem); } } else { tmp_elem.resize(5); tmp_elem[0] = 2; tmp_elem[1] = 0; for (size_t i = 0; i < element.size(); i++) { for (size_t j = 0; j < 3; j++) { tmp_elem[j+2] = element[i].vert[j]->id; if (out_packed == NotPacked) tmp_elem[j+2] += 1; } if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size(); rgst_elem.push_back(tmp_elem); } } return; } template void gmshio::element_register(const array> &element, const _2i_matrix *tag_ptr, array *rgst_index) { if (tag_ptr != nullptr && tag_ptr->row_size() != element.size()) { throw runtime_error("Tag size doesn't match with the element size. From gctl::gmshio::element_register(...)"); } if (rgst_index != nullptr) rgst_index->resize(element.size()); rgst_elem.reserve(rgst_elem.size() + element.size()); std::vector tmp_elem; if (tag_ptr != nullptr) { size_t c_size = tag_ptr->col_size(); tmp_elem.resize(8 + c_size); tmp_elem[0] = 9; tmp_elem[1] = c_size; for (size_t i = 0; i < element.size(); i++) { for (size_t j = 0; j < c_size; j++) { tmp_elem[j+2] = tag_ptr->at(i, j); } for (size_t j = 0; j < 6; j++) { tmp_elem[j+2+c_size] = element[i].vert[j]->id; if (out_packed == NotPacked) tmp_elem[j+2+c_size] += 1; } if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size(); rgst_elem.push_back(tmp_elem); } } else { tmp_elem.resize(8); tmp_elem[0] = 9; tmp_elem[1] = 0; for (size_t i = 0; i < element.size(); i++) { for (size_t j = 0; j < 6; j++) { tmp_elem[j+2] = element[i].vert[j]->id; if (out_packed == NotPacked) tmp_elem[j+2] += 1; } if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size(); rgst_elem.push_back(tmp_elem); } } return; } template void gmshio::element_register(const array> &element, const _2i_matrix *tag_ptr, array *rgst_index) { if (tag_ptr != nullptr && tag_ptr->row_size() != element.size()) { throw runtime_error("Tag size doesn't match with the element size. From gctl::gmshio::element_register(...)"); } if (rgst_index != nullptr) rgst_index->resize(element.size()); rgst_elem.reserve(rgst_elem.size() + element.size()); std::vector tmp_elem; if (tag_ptr != nullptr) { size_t c_size = tag_ptr->col_size(); tmp_elem.resize(6 + c_size); tmp_elem[0] = 3; tmp_elem[1] = c_size; for (size_t i = 0; i < element.size(); i++) { for (size_t j = 0; j < c_size; j++) { tmp_elem[j+2] = tag_ptr->at(i, j); } for (size_t j = 0; j < 4; j++) { tmp_elem[j+2+c_size] = element[i].vert[j]->id; if (out_packed == NotPacked) tmp_elem[j+2+c_size] += 1; } if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size(); rgst_elem.push_back(tmp_elem); } } else { tmp_elem.resize(6); tmp_elem[0] = 3; tmp_elem[1] = 0; for (size_t i = 0; i < element.size(); i++) { for (size_t j = 0; j < 4; j++) { tmp_elem[j+2] = element[i].vert[j]->id; if (out_packed == NotPacked) tmp_elem[j+2] += 1; } if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size(); rgst_elem.push_back(tmp_elem); } } return; } template void gmshio::element_register(const array> &element, const _2i_matrix *tag_ptr, array *rgst_index) { if (tag_ptr != nullptr && tag_ptr->row_size() != element.size()) { throw runtime_error("Tag size doesn't match with the element size. From gctl::gmshio::element_register(...)"); } if (rgst_index != nullptr) rgst_index->resize(element.size()); rgst_elem.reserve(rgst_elem.size() + element.size()); std::vector tmp_elem; if (tag_ptr != nullptr) { size_t c_size = tag_ptr->col_size(); tmp_elem.resize(3 + c_size); tmp_elem[0] = 15; tmp_elem[1] = c_size; for (size_t i = 0; i < element.size(); i++) { for (size_t j = 0; j < c_size; j++) { tmp_elem[j+2] = tag_ptr->at(i, j); } tmp_elem[2+c_size] = element[i].vert[0]->id; if (out_packed == NotPacked) tmp_elem[2+c_size] += 1; if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size(); rgst_elem.push_back(tmp_elem); } } else { tmp_elem.resize(3); tmp_elem[0] = 15; tmp_elem[1] = 0; for (size_t i = 0; i < element.size(); i++) { tmp_elem[2] = element[i].vert[0]->id; if (out_packed == NotPacked) tmp_elem[2] += 1; if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size(); rgst_elem.push_back(tmp_elem); } } return; } template void gmshio::element_register(const array> &element, const _2i_matrix *tag_ptr, array *rgst_index) { if (tag_ptr != nullptr && tag_ptr->row_size() != element.size()) { throw runtime_error("Tag size doesn't match with the element size. From gctl::gmshio::element_register(...)"); } if (rgst_index != nullptr) rgst_index->resize(element.size()); rgst_elem.reserve(rgst_elem.size() + element.size()); std::vector tmp_elem; if (tag_ptr != nullptr) { size_t c_size = tag_ptr->col_size(); tmp_elem.resize(5 + c_size); tmp_elem[0] = 2; tmp_elem[1] = c_size; for (size_t i = 0; i < element.size(); i++) { for (size_t j = 0; j < c_size; j++) { tmp_elem[j+2] = tag_ptr->at(i, j); } for (size_t j = 0; j < 3; j++) { tmp_elem[j+2+c_size] = element[i].vert[j]->id; if (out_packed == NotPacked) tmp_elem[j+2+c_size] += 1; } if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size(); rgst_elem.push_back(tmp_elem); } } else { tmp_elem.resize(5); tmp_elem[0] = 2; tmp_elem[1] = 0; for (size_t i = 0; i < element.size(); i++) { for (size_t j = 0; j < 3; j++) { tmp_elem[j+2] = element[i].vert[j]->id; if (out_packed == NotPacked) tmp_elem[j+2] += 1; } if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size(); rgst_elem.push_back(tmp_elem); } } return; } template void gmshio::element_register(const array> &element, const _2i_matrix *tag_ptr, array *rgst_index) { if (tag_ptr != nullptr && tag_ptr->row_size() != element.size()) { throw runtime_error("Tag size doesn't match with the element size. From gctl::gmshio::element_register(...)"); } if (rgst_index != nullptr) rgst_index->resize(element.size()); rgst_elem.reserve(rgst_elem.size() + element.size()); std::vector tmp_elem; if (tag_ptr != nullptr) { size_t c_size = tag_ptr->col_size(); tmp_elem.resize(6 + c_size); tmp_elem[0] = 4; tmp_elem[1] = c_size; for (size_t i = 0; i < element.size(); i++) { for (size_t j = 0; j < c_size; j++) { tmp_elem[j+2] = tag_ptr->at(i, j); } for (size_t j = 0; j < 4; j++) { tmp_elem[j+2+c_size] = element[i].vert[j]->id; if (out_packed == NotPacked) tmp_elem[j+2+c_size] += 1; } if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size(); rgst_elem.push_back(tmp_elem); } } else { tmp_elem.resize(6); tmp_elem[0] = 4; tmp_elem[1] = 0; for (size_t i = 0; i < element.size(); i++) { for (size_t j = 0; j < 4; j++) { tmp_elem[j+2] = element[i].vert[j]->id; if (out_packed == NotPacked) tmp_elem[j+2] += 1; } if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size(); rgst_elem.push_back(tmp_elem); } } return; } template void gmshio::element_register(const array> &element, const _2i_matrix *tag_ptr, array *rgst_index) { if (tag_ptr != nullptr && tag_ptr->row_size() != element.size()) { throw runtime_error("Tag size doesn't match with the element size. From gctl::gmshio::element_register(...)"); } if (rgst_index != nullptr) rgst_index->resize(element.size()); rgst_elem.reserve(rgst_elem.size() + element.size()); std::vector tmp_elem; if (tag_ptr != nullptr) { size_t c_size = tag_ptr->col_size(); tmp_elem.resize(10 + c_size); tmp_elem[0] = 5; tmp_elem[1] = c_size; for (size_t i = 0; i < element.size(); i++) { for (size_t j = 0; j < c_size; j++) { tmp_elem[j+2] = tag_ptr->at(i, j); } for (size_t j = 0; j < 8; j++) { tmp_elem[j+2+c_size] = element[i].vert[j]->id; if (out_packed == NotPacked) tmp_elem[j+2+c_size] += 1; } if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size(); rgst_elem.push_back(tmp_elem); } } else { tmp_elem.resize(10); tmp_elem[0] = 5; tmp_elem[1] = 0; for (size_t i = 0; i < element.size(); i++) { for (size_t j = 0; j < 8; j++) { tmp_elem[j+2] = element[i].vert[j]->id; if (out_packed == NotPacked) tmp_elem[j+2] += 1; } if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size(); rgst_elem.push_back(tmp_elem); } } return; } template void gmshio::element_register(const array> &element, const _2i_matrix *tag_ptr, array *rgst_index) { if (tag_ptr != nullptr && tag_ptr->row_size() != element.size()) { throw runtime_error("Tag size doesn't match with the element size. From gctl::gmshio::element_register(...)"); } if (rgst_index != nullptr) rgst_index->resize(element.size()); rgst_elem.reserve(rgst_elem.size() + element.size()); std::vector tmp_elem; if (tag_ptr != nullptr) { size_t c_size = tag_ptr->col_size(); tmp_elem.resize(6 + c_size); tmp_elem[0] = 4; tmp_elem[1] = c_size; for (size_t i = 0; i < element.size(); i++) { for (size_t j = 0; j < c_size; j++) { tmp_elem[j+2] = tag_ptr->at(i, j); } for (size_t j = 0; j < 4; j++) { tmp_elem[j+2+c_size] = element[i].vert[j]->id; if (out_packed == NotPacked) tmp_elem[j+2+c_size] += 1; } if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size(); rgst_elem.push_back(tmp_elem); } } else { tmp_elem.resize(6); tmp_elem[0] = 4; tmp_elem[1] = 0; for (size_t i = 0; i < element.size(); i++) { for (size_t j = 0; j < 4; j++) { tmp_elem[j+2] = element[i].vert[j]->id; if (out_packed == NotPacked) tmp_elem[j+2] += 1; } if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size(); rgst_elem.push_back(tmp_elem); } } return; } template void gmshio::element_register(const array> &element, const _2i_matrix *tag_ptr, array *rgst_index) { if (tag_ptr != nullptr && tag_ptr->row_size() != element.size()) { throw runtime_error("Tag size doesn't match with the element size. From gctl::gmshio::element_register(...)"); } if (rgst_index != nullptr) rgst_index->resize(element.size()); rgst_elem.reserve(rgst_elem.size() + element.size()); std::vector tmp_elem; if (tag_ptr != nullptr) { size_t c_size = tag_ptr->col_size(); tmp_elem.resize(8 + c_size); tmp_elem[0] = 6; tmp_elem[1] = c_size; for (size_t i = 0; i < element.size(); i++) { for (size_t j = 0; j < c_size; j++) { tmp_elem[j+2] = tag_ptr->at(i, j); } for (size_t j = 0; j < 6; j++) { tmp_elem[j+2+c_size] = element[i].vert[j]->id; if (out_packed == NotPacked) tmp_elem[j+2+c_size] += 1; } if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size(); rgst_elem.push_back(tmp_elem); } } else { tmp_elem.resize(8); tmp_elem[0] = 6; tmp_elem[1] = 0; for (size_t i = 0; i < element.size(); i++) { for (size_t j = 0; j < 6; j++) { tmp_elem[j+2] = element[i].vert[j]->id; if (out_packed == NotPacked) tmp_elem[j+2] += 1; } if (rgst_index != nullptr) rgst_index->at(i) = rgst_elem.size(); rgst_elem.push_back(tmp_elem); } } return; } template void gmshio::save_registered_mesh(const array> &node, array *phys_ptr) { initialized(Output); if (rgst_elem.empty()) { throw runtime_error("No registered elemets found. From gmshio::save_registered_mesh(...)"); } // save head info // 将文件指针重置到文件头 保险一点 gmsh_out.clear(std::ios::goodbit); gmsh_out.seekp(0, std::ios::beg); gmsh_out << "$MeshFormat" << std::endl << "2.2 0 8" << std::endl << "$EndMeshFormat "<size() << "\n"; for (size_t i = 0; i < phys_ptr->size(); i++) { gmsh_out << phys_ptr->at(i).dim_tag << " " << phys_ptr->at(i).phys_tag << " \"" << phys_ptr->at(i).name << "\"\n"; } gmsh_out << "$EndPhysicalNames\n"; } // save node save2gmsh_node(gmsh_out, node.get(), node.size(), out_packed); // save elements gmsh_out << "$Elements" << std::endl << rgst_elem.size() < void gmshio::save_registered_mesh(const array> &node, array *phys_ptr) { initialized(Output); if (rgst_elem.empty()) { throw runtime_error("No registered elemets found. From gmshio::save_registered_mesh(...)"); } // save head info // 将文件指针重置到文件头 保险一点 gmsh_out.clear(std::ios::goodbit); gmsh_out.seekp(0, std::ios::beg); gmsh_out << "$MeshFormat" << std::endl << "2.2 0 8" << std::endl << "$EndMeshFormat "<size() << "\n"; for (size_t i = 0; i < phys_ptr->size(); i++) { gmsh_out << phys_ptr->at(i).dim_tag << " " << phys_ptr->at(i).phys_tag << " \"" << phys_ptr->at(i).name << "\"\n"; } gmsh_out << "$EndPhysicalNames\n"; } // save node save2gmsh_node(gmsh_out, node.get(), node.size(), out_packed); // save elements gmsh_out << "$Elements" << std::endl << rgst_elem.size() < void read_gmsh_node(std::ifstream &infile, array> &node, index_packed_e packed = Packed) { // 重置数据 if (!node.empty()) node.clear(); // 将文件指针重置到文件头 infile.clear(std::ios::goodbit); infile.seekg(std::ios::beg); int n_size = 0; std::string tmp_str; std::stringstream tmp_ss; while(getline(infile,tmp_str)) { if (tmp_str == "$Nodes") //读入模型空间顶点集 msh文件版本为2.2 { getline(infile, tmp_str); gctl::str2ss(tmp_str, tmp_ss); tmp_ss >> n_size; //第一个数为顶点的个数 node.resize(n_size); for (int i = 0; i < n_size; i++) { getline(infile, tmp_str); str2ss(tmp_str, tmp_ss); tmp_ss >> node[i].id >> node[i].x >> node[i].y; if (packed == NotPacked) node[i].id -= 1; } break; } } return; } /** * @brief Read nodes from a Gmsh file. * * @param[in] infile The input file stream * @param node an array object * @param[in] packed Indicates whether the index in the node file starts from zero. The * index is deemed to be started with one if this option is false. The default value of this * variable is true. * */ template void read_gmsh_node(std::ifstream &infile, array> &node, index_packed_e packed = Packed) { // 重置数据 if (!node.empty()) node.clear(); // 将文件指针重置到文件头 infile.clear(std::ios::goodbit); infile.seekg(std::ios::beg); int n_size = 0; std::string tmp_str; std::stringstream tmp_ss; while(getline(infile,tmp_str)) { if (tmp_str == "$Nodes") //读入模型空间顶点集 msh文件版本为2.2 { getline(infile,tmp_str); gctl::str2ss(tmp_str, tmp_ss); tmp_ss >> n_size; //第一个数为顶点的个数 node.resize(n_size); for (int i = 0; i < n_size; i++) { getline(infile,tmp_str); str2ss(tmp_str, tmp_ss); tmp_ss >> node[i].id >> node[i].x >> node[i].y >> node[i].z; if (packed == NotPacked) node[i].id -= 1; } break; } } return; } /** * @brief Read element index from a Gmsh file. * * @param[in] infile The input file stream * @param element The output element object array * @param node The node array * @param[in] packed Indicates whether the index in the node file starts from zero. The * index is deemed to be started with one if this option is false. The default value of this * variable is true. * @param[in] ele_tag Return elements' tags by a 2D integer vector. * */ template void read_gmsh_element(std::ifstream &infile, array> &element, const array> &node, index_packed_e packed = Packed, _2i_vector *ele_tag = nullptr) { if (node.empty()) throw runtime_error("The input array is empty. From gctl::read_gmsh_element(...)"); // 重置数据 if (!element.empty()) element.clear(); // 重置标签 if (ele_tag != nullptr && !ele_tag->empty()) ele_tag->clear(); // 将文件指针重置到文件头 infile.clear(std::ios::goodbit); infile.seekg(std::ios::beg); int i_size = 0, ele_count = 0; int tmp_int, ele_type, attri_num; int tmp_index[2]; std::string tmp_str; std::stringstream tmp_ss; while(getline(infile,tmp_str)) { if (tmp_str == "$Elements") //读入模型空间顶点集 msh文件版本为2.2 { getline(infile,tmp_str); gctl::str2ss(tmp_str, tmp_ss); tmp_ss >> i_size; //第一个数为顶点的个数 // 我们先用一个临时的向量来储存元素 edge2d tmp_edge; std::vector element_vec; std::vector tmp_tag; for (int i = 0; i < i_size; i++) { getline(infile,tmp_str); str2ss(tmp_str, tmp_ss); tmp_ss >> tmp_int >> ele_type >> attri_num; if (ele_type == 1) { tmp_edge.id = ele_count; tmp_tag.clear(); for (int a = 0; a < attri_num; a++) { tmp_ss >> tmp_int; tmp_tag.push_back(tmp_int); } if (ele_tag != nullptr) ele_tag->push_back(tmp_tag); tmp_ss >> tmp_index[0] >> tmp_index[1]; if (packed == NotPacked) { for (int j = 0; j < 2; j++) tmp_edge.vert[j] = node.get(tmp_index[j]-1); } else { for (int j = 0; j < 2; j++) tmp_edge.vert[j] = node.get(tmp_index[j]); } element_vec.push_back(tmp_edge); ele_count++; } } //将元素转移到向量上来 element.resize(element_vec.size()); for (int i = 0; i < element.size(); i++) { element[i].id = element_vec[i].id; for (int j = 0; j < 2; j++) element[i].vert[j] = element_vec[i].vert[j]; } destroy_vector(element_vec); break; } } return; } /** * @brief Read element index from a Gmsh file. * * @param[in] infile The input file stream * @param element The output element object array * @param node The node array * @param[in] packed Indicates whether the index in the node file starts from zero. The * index is deemed to be started with one if this option is false. The default value of this * variable is true. * @param[in] ele_tag Return elements' tags by a 2D integer vector. * */ template void read_gmsh_element(std::ifstream &infile, array> &element, const array> &node, index_packed_e packed = Packed, _2i_vector *ele_tag = nullptr) { if (node.empty()) throw runtime_error("The input array is empty. From gctl::read_gmsh_element(...)"); // 重置数据 if (!element.empty()) element.clear(); // 重置标签 if (ele_tag != nullptr && !ele_tag->empty()) ele_tag->clear(); // 将文件指针重置到文件头 infile.clear(std::ios::goodbit); infile.seekg(std::ios::beg); int i_size = 0, ele_count = 0; int tmp_int, ele_type, attri_num; int tmp_index[3]; std::string tmp_str; std::stringstream tmp_ss; while(getline(infile,tmp_str)) { if (tmp_str == "$Elements") //读入模型空间顶点集 msh文件版本为2.2 { getline(infile,tmp_str); gctl::str2ss(tmp_str, tmp_ss); tmp_ss >> i_size; //第一个数为顶点的个数 // 我们先用一个临时的向量来储存元素 triangle2d tmp_tri; std::vector element_vec; std::vector tmp_tag; for (int i = 0; i < i_size; i++) { getline(infile,tmp_str); str2ss(tmp_str, tmp_ss); tmp_ss >> tmp_int >> ele_type >> attri_num; if (ele_type == 2) { tmp_tri.id = ele_count; tmp_tag.clear(); for (int a = 0; a < attri_num; a++) { tmp_ss >> tmp_int; tmp_tag.push_back(tmp_int); } if (ele_tag != nullptr) ele_tag->push_back(tmp_tag); tmp_ss >> tmp_index[0] >> tmp_index[1] >> tmp_index[2]; if (packed == NotPacked) { for (int j = 0; j < 3; j++) tmp_tri.vert[j] = node.get(tmp_index[j]-1); } else { for (int j = 0; j < 3; j++) tmp_tri.vert[j] = node.get(tmp_index[j]); } element_vec.push_back(tmp_tri); ele_count++; } } //将元素转移到向量上来 element.resize(element_vec.size()); for (int i = 0; i < element.size(); i++) { element[i].id = element_vec[i].id; for (int j = 0; j < 3; j++) element[i].vert[j] = element_vec[i].vert[j]; } destroy_vector(element_vec); break; } } return; } /** * @brief Read element index from a Gmsh file. * * @param[in] infile The input file stream * @param element The output element object array * @param node The node array * @param[in] packed Indicates whether the index in the node file starts from zero. The * index is deemed to be started with one if this option is false. The default value of this * variable is true. * @param[in] ele_tag Return elements' tags by a 2D integer vector. * */ template void read_gmsh_element(std::ifstream &infile, array> &element, const array> &node, index_packed_e packed = Packed, _2i_vector *ele_tag = nullptr) { if (node.empty()) throw runtime_error("The input array is empty. From gctl::read_gmsh_element(...)"); // 重置数据 if (!element.empty()) element.clear(); // 重置标签 if (ele_tag != nullptr && !ele_tag->empty()) ele_tag->clear(); // 将文件指针重置到文件头 infile.clear(std::ios::goodbit); infile.seekg(std::ios::beg); int i_size = 0, ele_count = 0; int tmp_int, ele_type, attri_num; int tmp_index[6]; std::string tmp_str; std::stringstream tmp_ss; while(getline(infile,tmp_str)) { if (tmp_str == "$Elements") //读入模型空间顶点集 msh文件版本为2.2 { getline(infile,tmp_str); gctl::str2ss(tmp_str, tmp_ss); tmp_ss >> i_size; //第一个数为顶点的个数 // 我们先用一个临时的向量来储存元素 triangle2d2o tmp_tri; std::vector element_vec; std::vector tmp_tag; for (int i = 0; i < i_size; i++) { getline(infile,tmp_str); str2ss(tmp_str, tmp_ss); tmp_ss >> tmp_int >> ele_type >> attri_num; if (ele_type == 9) { tmp_tri.id = ele_count; tmp_tag.clear(); for (int a = 0; a < attri_num; a++) { tmp_ss >> tmp_int; tmp_tag.push_back(tmp_int); } if (ele_tag != nullptr) ele_tag->push_back(tmp_tag); tmp_ss >> tmp_index[0] >> tmp_index[1] >> tmp_index[2] >> tmp_index[3] >> tmp_index[4] >> tmp_index[5]; if (packed == NotPacked) { for (int j = 0; j < 3; j++) tmp_tri.vert[j] = node.get(tmp_index[j]-1); tmp_tri.vert[5] = node.get(tmp_index[3]-1); tmp_tri.vert[3] = node.get(tmp_index[4]-1); tmp_tri.vert[4] = node.get(tmp_index[5]-1); } else { for (int j = 0; j < 3; j++) tmp_tri.vert[j] = node.get(tmp_index[j]); tmp_tri.vert[5] = node.get(tmp_index[3]); tmp_tri.vert[3] = node.get(tmp_index[4]); tmp_tri.vert[4] = node.get(tmp_index[5]); } element_vec.push_back(tmp_tri); ele_count++; } } //将元素转移到向量上来 element.resize(element_vec.size()); for (int i = 0; i < element.size(); i++) { element[i].id = element_vec[i].id; for (int j = 0; j < 6; j++) element[i].vert[j] = element_vec[i].vert[j]; } destroy_vector(element_vec); break; } } return; } template void read_gmsh_element(std::ifstream &infile, array> &element, const array> &node, index_packed_e packed = Packed, _2i_vector *ele_tag = nullptr) { if (node.empty()) throw runtime_error("The input array is empty. From gctl::read_gmsh_element(...)"); // 重置数据 if (!element.empty()) element.clear(); // 重置标签 if (ele_tag != nullptr && !ele_tag->empty()) ele_tag->clear(); // 将文件指针重置到文件头 infile.clear(std::ios::goodbit); infile.seekg(std::ios::beg); int i_size = 0, ele_count = 0; int tmp_int, ele_type, attri_num; int tmp_index[4]; std::string tmp_str; std::stringstream tmp_ss; while(getline(infile,tmp_str)) { if (tmp_str == "$Elements") //读入模型空间顶点集 msh文件版本为2.2 { getline(infile,tmp_str); gctl::str2ss(tmp_str, tmp_ss); tmp_ss >> i_size; //第一个数为顶点的个数 // 我们先用一个临时的向量来储存元素 rectangle2d tmp_rect; std::vector element_vec; std::vector tmp_tag; for (int i = 0; i < i_size; i++) { getline(infile,tmp_str); str2ss(tmp_str, tmp_ss); tmp_ss >> tmp_int >> ele_type >> attri_num; if (ele_type == 3) { tmp_rect.id = ele_count; tmp_tag.clear(); for (int a = 0; a < attri_num; a++) { tmp_ss >> tmp_int; tmp_tag.push_back(tmp_int); } if (ele_tag != nullptr) ele_tag->push_back(tmp_tag); tmp_ss >> tmp_index[0] >> tmp_index[1] >> tmp_index[2] >> tmp_index[3]; if (packed == NotPacked) { tmp_rect.dl = node.get(tmp_index[0]-1); tmp_rect.ur = node.get(tmp_index[2]-1); for (int j = 0; j < 4; j++) { tmp_rect.vert[j] = node.get(tmp_index[j]-1); } } else { tmp_rect.dl = node.get(tmp_index[0]); tmp_rect.ur = node.get(tmp_index[2]); for (int j = 0; j < 4; j++) tmp_rect.vert[j] = node.get(tmp_index[j]); } element_vec.push_back(tmp_rect); ele_count++; } } //将元素转移到向量上来 element.resize(element_vec.size()); for (int i = 0; i < element.size(); i++) { element[i].id = element_vec[i].id; element[i].dl = element_vec[i].dl; element[i].ur = element_vec[i].ur; for (int j = 0; j < 4; j++) element[i].vert[j] = element_vec[i].vert[j]; } destroy_vector(element_vec); break; } } return; } template void read_gmsh_element(std::ifstream &infile, array> &element, const array> &node, index_packed_e packed = Packed, _2i_vector *ele_tag = nullptr) { if (node.empty()) throw runtime_error("The input array is empty. From gctl::read_gmsh_element(...)"); // 重置数据 if (!element.empty()) element.clear(); // 重置标签 if (ele_tag != nullptr && !ele_tag->empty()) ele_tag->clear(); // 将文件指针重置到文件头 infile.clear(std::ios::goodbit); infile.seekg(std::ios::beg); int i_size = 0, ele_count = 0; int tmp_int, ele_type, attri_num; int tmp_index; std::string tmp_str; std::stringstream tmp_ss; while(getline(infile,tmp_str)) { if (tmp_str == "$Elements") //读入模型空间顶点集 msh文件版本为2.2 { getline(infile,tmp_str); gctl::str2ss(tmp_str, tmp_ss); tmp_ss >> i_size; //第一个数为顶点的个数 // 我们先用一个临时的向量来储存元素 enode tmp_node; std::vector element_vec; std::vector tmp_tag; for (int i = 0; i < i_size; i++) { getline(infile,tmp_str); str2ss(tmp_str, tmp_ss); tmp_ss >> tmp_int >> ele_type >> attri_num; if (ele_type == 15) { tmp_node.id = ele_count; tmp_tag.clear(); for (int a = 0; a < attri_num; a++) { tmp_ss >> tmp_int; tmp_tag.push_back(tmp_int); } if (ele_tag != nullptr) ele_tag->push_back(tmp_tag); tmp_ss >> tmp_index; if (packed == NotPacked) tmp_node.vert[0] = node.get(tmp_index-1); else tmp_node.vert[0] = node.get(tmp_index); element_vec.push_back(tmp_node); ele_count++; } } //将元素转移到向量上来 element.resize(element_vec.size()); for (int i = 0; i < element.size(); i++) { element[i].id = element_vec[i].id; element[i].vert[0] = element_vec[i].vert[0]; } destroy_vector(element_vec); break; } } return; } template void read_gmsh_element(std::ifstream &infile, array> &element, const array> &node, index_packed_e packed = Packed, _2i_vector *ele_tag = nullptr) { if (node.empty()) throw runtime_error("The input array is empty. From gctl::read_gmsh_element(...)"); // 重置数据 if (!element.empty()) element.clear(); // 重置标签 if (ele_tag != nullptr && !ele_tag->empty()) ele_tag->clear(); // 将文件指针重置到文件头 infile.clear(std::ios::goodbit); infile.seekg(std::ios::beg); int i_size = 0, ele_count = 0; int tmp_int, ele_type, attri_num; int tmp_index[2]; std::string tmp_str; std::stringstream tmp_ss; while(getline(infile,tmp_str)) { if (tmp_str == "$Elements") //读入模型空间顶点集 msh文件版本为2.2 { getline(infile,tmp_str); gctl::str2ss(tmp_str, tmp_ss); tmp_ss >> i_size; //第一个数为顶点的个数 // 我们先用一个临时的向量来储存元素 edge tmp_tri; std::vector element_vec; std::vector tmp_tag; for (int i = 0; i < i_size; i++) { getline(infile,tmp_str); str2ss(tmp_str, tmp_ss); tmp_ss >> tmp_int >> ele_type >> attri_num; if (ele_type == 1) { tmp_tri.id = ele_count; tmp_tag.clear(); for (int a = 0; a < attri_num; a++) { tmp_ss >> tmp_int; tmp_tag.push_back(tmp_int); } if (ele_tag != nullptr) ele_tag->push_back(tmp_tag); tmp_ss >> tmp_index[0] >> tmp_index[1]; if (packed == NotPacked) { for (int j = 0; j < 2; j++) tmp_tri.vert[j] = node.get(tmp_index[j]-1); } else { for (int j = 0; j < 2; j++) tmp_tri.vert[j] = node.get(tmp_index[j]); } element_vec.push_back(tmp_tri); ele_count++; } } //将元素转移到向量上来 element.resize(element_vec.size()); for (int i = 0; i < element.size(); i++) { element[i].id = element_vec[i].id; for (int j = 0; j < 2; j++) element[i].vert[j] = element_vec[i].vert[j]; } destroy_vector(element_vec); break; } } return; } template void read_gmsh_element(std::ifstream &infile, array> &element, const array> &node, index_packed_e packed = Packed, _2i_vector *ele_tag = nullptr) { if (node.empty()) throw runtime_error("The input array is empty. From gctl::read_gmsh_element(...)"); // 重置数据 if (!element.empty()) element.clear(); // 重置标签 if (ele_tag != nullptr && !ele_tag->empty()) ele_tag->clear(); // 将文件指针重置到文件头 infile.clear(std::ios::goodbit); infile.seekg(std::ios::beg); int i_size = 0, ele_count = 0; int tmp_int, ele_type, attri_num; int tmp_index[3]; std::string tmp_str; std::stringstream tmp_ss; while(getline(infile,tmp_str)) { if (tmp_str == "$Elements") //读入模型空间顶点集 msh文件版本为2.2 { getline(infile,tmp_str); gctl::str2ss(tmp_str, tmp_ss); tmp_ss >> i_size; //第一个数为顶点的个数 // 我们先用一个临时的向量来储存元素 triangle tmp_tri; std::vector element_vec; std::vector tmp_tag; for (int i = 0; i < i_size; i++) { getline(infile,tmp_str); str2ss(tmp_str, tmp_ss); tmp_ss >> tmp_int >> ele_type >> attri_num; if (ele_type == 2) { tmp_tri.id = ele_count; tmp_tag.clear(); for (int a = 0; a < attri_num; a++) { tmp_ss >> tmp_int; tmp_tag.push_back(tmp_int); } if (ele_tag != nullptr) ele_tag->push_back(tmp_tag); tmp_ss >> tmp_index[0] >> tmp_index[1] >> tmp_index[2]; if (packed == NotPacked) { for (int j = 0; j < 3; j++) tmp_tri.vert[j] = node.get(tmp_index[j]-1); } else { for (int j = 0; j < 3; j++) tmp_tri.vert[j] = node.get(tmp_index[j]); } element_vec.push_back(tmp_tri); ele_count++; } } //将元素转移到向量上来 element.resize(element_vec.size()); for (int i = 0; i < element.size(); i++) { element[i].id = element_vec[i].id; for (int j = 0; j < 3; j++) element[i].vert[j] = element_vec[i].vert[j]; } destroy_vector(element_vec); break; } } return; } template void read_gmsh_element(std::ifstream &infile, array> &element, const array> &node, index_packed_e packed = Packed, _2i_vector *ele_tag = nullptr) { if (node.empty()) throw runtime_error("The input array is empty. From gctl::read_gmsh_element(...)"); // 重置数据 if (!element.empty()) element.clear(); // 重置标签 if (ele_tag != nullptr && !ele_tag->empty()) ele_tag->clear(); // 将文件指针重置到文件头 infile.clear(std::ios::goodbit); infile.seekg(std::ios::beg); int i_size = 0, ele_count = 0; int tmp_int, ele_type, attri_num; int tmp_index[4]; std::string tmp_str; std::stringstream tmp_ss; while(getline(infile,tmp_str)) { if (tmp_str == "$Elements") //读入模型空间顶点集 msh文件版本为2.2 { getline(infile,tmp_str); gctl::str2ss(tmp_str, tmp_ss); tmp_ss >> i_size; //第一个数为顶点的个数 // 我们先用一个临时的向量来储存元素 tetrahedron tmp_tet; std::vector element_vec; std::vector tmp_tag; for (int i = 0; i < i_size; i++) { getline(infile,tmp_str); str2ss(tmp_str, tmp_ss); tmp_ss >> tmp_int >> ele_type >> attri_num; if (ele_type == 4) { tmp_tet.id = ele_count; tmp_tag.clear(); for (int a = 0; a < attri_num; a++) { tmp_ss >> tmp_int; tmp_tag.push_back(tmp_int); } if (ele_tag != nullptr) ele_tag->push_back(tmp_tag); tmp_ss >> tmp_index[0] >> tmp_index[1] >> tmp_index[2] >> tmp_index[3]; if (packed == NotPacked) { for (int j = 0; j < 4; j++) tmp_tet.vert[j] = node.get(tmp_index[j]-1); } else { for (int j = 0; j < 4; j++) tmp_tet.vert[j] = node.get(tmp_index[j]); } element_vec.push_back(tmp_tet); ele_count++; } } //将元素转移到向量上来 element.resize(element_vec.size()); for (int i = 0; i < element.size(); i++) { element[i].id = element_vec[i].id; for (int j = 0; j < 4; j++) { element[i].vert[j] = element_vec[i].vert[j]; } element[i].deter_vert_order(); } destroy_vector(element_vec); break; } } return; } template void read_gmsh_element(std::ifstream &infile, array> &element, const array> &node, index_packed_e packed = Packed, _2i_vector *ele_tag = nullptr) { if (node.empty()) throw runtime_error("The input array is empty. From gctl::read_gmsh_element(...)"); // 重置数据 if (!element.empty()) element.clear(); // 重置标签 if (ele_tag != nullptr && !ele_tag->empty()) ele_tag->clear(); // 将文件指针重置到文件头 infile.clear(std::ios::goodbit); infile.seekg(std::ios::beg); int i_size = 0, ele_count = 0; int tmp_int, ele_type, attri_num; int tmp_index[8]; std::string tmp_str; std::stringstream tmp_ss; while(getline(infile,tmp_str)) { if (tmp_str == "$Elements") //读入模型空间顶点集 msh文件版本为2.2 { getline(infile,tmp_str); gctl::str2ss(tmp_str, tmp_ss); tmp_ss >> i_size; //第一个数为顶点的个数 // 我们先用一个临时的向量来储存元素 block tmp_block; std::vector element_vec; std::vector tmp_tag; for (int i = 0; i < i_size; i++) { getline(infile,tmp_str); str2ss(tmp_str, tmp_ss); tmp_ss >> tmp_int >> ele_type >> attri_num; if (ele_type == 5) { tmp_block.id = ele_count; tmp_tag.clear(); for (int a = 0; a < attri_num; a++) { tmp_ss >> tmp_int; tmp_tag.push_back(tmp_int); } if (ele_tag != nullptr) ele_tag->push_back(tmp_tag); for (int a = 0; a < 8; a++) tmp_ss >> tmp_index[a]; if (packed == NotPacked) { tmp_block.dl = node.get(tmp_index[0]-1); tmp_block.ur = node.get(tmp_index[6]-1); for (int j = 0; j < 8; j++) { tmp_block.vert[j] = node.get(tmp_index[j]-1); } } else { tmp_block.dl = node.get(tmp_index[0]); tmp_block.ur = node.get(tmp_index[6]); for (int j = 0; j < 8; j++) { tmp_block.vert[j] = node.get(tmp_index[j]); } } element_vec.push_back(tmp_block); ele_count++; } } //将元素转移到向量上来 element.resize(element_vec.size()); for (int i = 0; i < element.size(); i++) { element[i].id = element_vec[i].id; element[i].dl = element_vec[i].dl; element[i].ur = element_vec[i].ur; for (int j = 0; j < 8; j++) element[i].vert[j] = element_vec[i].vert[j]; } destroy_vector(element_vec); break; } } return; } template void read_gmsh_element(std::ifstream &infile, array> &element, const array> &node, index_packed_e packed = Packed, _2i_vector *ele_tag = nullptr) { if (node.empty()) throw runtime_error("The input array is empty. From gctl::read_gmsh_element(...)"); // 重置数据 if (!element.empty()) element.clear(); // 重置标签 if (ele_tag != nullptr && !ele_tag->empty()) ele_tag->clear(); // 将文件指针重置到文件头 infile.clear(std::ios::goodbit); infile.seekg(std::ios::beg); int i_size = 0, ele_count = 0; int tmp_int, ele_type, attri_num; int tmp_index[3]; std::string tmp_str; std::stringstream tmp_ss; while(getline(infile, tmp_str)) { if (tmp_str == "$Elements") //读入模型空间顶点集 msh文件版本为2.2 { getline(infile,tmp_str); gctl::str2ss(tmp_str, tmp_ss); tmp_ss >> i_size; //第一个数为顶点的个数 // 我们先用一个临时的向量来储存元素 tri_cone tmp_cone; std::vector element_vec; std::vector tmp_tag; for (int i = 0; i < i_size; i++) { getline(infile,tmp_str); str2ss(tmp_str, tmp_ss); tmp_ss >> tmp_int >> ele_type >> attri_num; if (ele_type == 2) { tmp_cone.id = ele_count; tmp_tag.clear(); for (int a = 0; a < attri_num; a++) { tmp_ss >> tmp_int; tmp_tag.push_back(tmp_int); } if (ele_tag != nullptr) ele_tag->push_back(tmp_tag); tmp_ss >> tmp_index[0] >> tmp_index[1] >> tmp_index[2]; if (packed == NotPacked) { for (int j = 0; j < 3; j++) { tmp_cone.vert[j] = node.get(tmp_index[j]-1); } } else { for (int j = 0; j < 3; j++) { tmp_cone.vert[j] = node.get(tmp_index[j]); } } element_vec.push_back(tmp_cone); ele_count++; } } //将元素转移到向量上来 element.resize(element_vec.size()); for (int i = 0; i < element.size(); i++) { element[i].id = element_vec[i].id; for (int j = 0; j < 3; j++) element[i].vert[j] = element_vec[i].vert[j]; } destroy_vector(element_vec); break; } } return; } template void read_gmsh_element(std::ifstream &infile, array> &element, const array> &node, index_packed_e packed = Packed, _2i_vector *ele_tag = nullptr) { if (node.empty()) throw runtime_error("The input array is empty. From gctl::read_gmsh_element(...)"); // 重置数据 if (!element.empty()) element.clear(); // 重置标签 if (ele_tag != nullptr && !ele_tag->empty()) ele_tag->clear(); // 将文件指针重置到文件头 infile.clear(std::ios::goodbit); infile.seekg(std::ios::beg); int i_size = 0, ele_count = 0; int tmp_int, ele_type, attri_num; int tmp_index[6]; std::string tmp_str; std::stringstream tmp_ss; while(getline(infile, tmp_str)) { if (tmp_str == "$Elements") //读入模型空间顶点集 msh文件版本为2.2 { getline(infile,tmp_str); gctl::str2ss(tmp_str, tmp_ss); tmp_ss >> i_size; //第一个数为顶点的个数 // 我们先用一个临时的向量来储存元素 prism tmp_prism; std::vector element_vec; std::vector tmp_tag; for (int i = 0; i < i_size; i++) { getline(infile,tmp_str); str2ss(tmp_str, tmp_ss); tmp_ss >> tmp_int >> ele_type >> attri_num; if (ele_type == 6) { tmp_prism.id = ele_count; tmp_tag.clear(); for (int a = 0; a < attri_num; a++) { tmp_ss >> tmp_int; tmp_tag.push_back(tmp_int); } if (ele_tag != nullptr) ele_tag->push_back(tmp_tag); tmp_ss >> tmp_index[0] >> tmp_index[1] >> tmp_index[2] >> tmp_index[3] >> tmp_index[4] >> tmp_index[5]; if (packed == NotPacked) { for (int j = 0; j < 6; j++) { tmp_prism.vert[j] = node.get(tmp_index[j]-1); } } else { for (int j = 0; j < 6; j++) { tmp_prism.vert[j] = node.get(tmp_index[j]); } } element_vec.push_back(tmp_prism); ele_count++; } } //将元素转移到向量上来 element.resize(element_vec.size()); for (int i = 0; i < element.size(); i++) { element[i].id = element_vec[i].id; for (int j = 0; j < 6; j++) element[i].vert[j] = element_vec[i].vert[j]; } destroy_vector(element_vec); break; } } return; } /** * @brief Read data block from a Gmsh .msh file. * * @param infile The input file stream * @param out_data Output data name * @param[in] data_name Name of the data block that will be output. The first data block will * be output if this no data name is given. */ template void read_gmsh_data(std::ifstream &infile, array &out_data, std::string data_name = "") { std::string requst_name = ""; if (data_name != "") requst_name = "\"" + data_name + "\""; // 将文件指针重置到文件头 infile.clear(std::ios::goodbit); infile.seekg(std::ios::beg); bool data_found = false; int tmp_int, data_size; std::string tmp_str; std::stringstream tmp_ss; while(getline(infile, tmp_str)) { if (tmp_str == "$NodeData" || tmp_str == "$ElementData") { //先读入元素块的名称 添加到数组 for (int i = 0; i < 2; i++) getline(infile, tmp_str); if (requst_name == "" || requst_name == tmp_str) { data_found = true; //跳过元素属性前面的值 最后一次为当前元素块的个数 for (int i = 0; i < 6; i++) getline(infile,tmp_str); gctl::str2ss(tmp_str, tmp_ss); tmp_ss >> data_size; out_data.resize(data_size); for (int i = 0; i < data_size; i++) { getline(infile,tmp_str); gctl::str2ss(tmp_str, tmp_ss); tmp_ss >> tmp_int >> out_data[i]; } break; } } } if (!data_found) { throw runtime_error("data not found for: " + data_name + ". From void gctl::read_gmsh_data(..)"); } return; } /** * @brief Read data block from a Gmsh .msh file. * * @param infile The input file stream * @param out_data Output data name * @param out_index Output data index * @param[in] data_name Name of the data block that will be output. The first data block will * be output if this no data name is given. * @param[in] packed Indicates whether the index in the node file starts from zero. The * index is deemed to be started with one if this option is false. The default value of this * variable is true. */ template void read_gmsh_data(std::ifstream &infile, array &out_data, array &out_index, std::string data_name = "", index_packed_e packed = Packed) { std::string requst_name = ""; if (data_name != "") requst_name = "\"" + data_name + "\""; // 将文件指针重置到文件头 infile.clear(std::ios::goodbit); infile.seekg(std::ios::beg); bool data_found = false; int tmp_int, data_size; std::string tmp_str; std::stringstream tmp_ss; while(getline(infile, tmp_str)) { if (tmp_str == "$NodeData" || tmp_str == "$ElementData") { //先读入元素块的名称 添加到数组 for (int i = 0; i < 2; i++) getline(infile, tmp_str); if (requst_name == "" || requst_name == tmp_str) { data_found = true; //跳过元素属性前面的值 最后一次为当前元素块的个数 for (int i = 0; i < 6; i++) getline(infile,tmp_str); gctl::str2ss(tmp_str, tmp_ss); tmp_ss >> data_size; out_data.resize(data_size); out_index.resize(data_size, -1); for (int i = 0; i < data_size; i++) { getline(infile,tmp_str); gctl::str2ss(tmp_str, tmp_ss); tmp_ss >> out_index[i] >> out_data[i]; } if (packed == NotPacked) { for (int i = 0; i < data_size; i++) out_index[i] -= 1; } break; } } } if (!data_found) { throw runtime_error("data not found for: " + data_name + ". From void gctl::read_gmsh_data(..)"); } return; } template void read_gmsh_data(std::ifstream &infile, std::vector > &out_data, std::vector &out_name, mesh_data_type_e d_type, std::vector > *out_index = nullptr, index_packed_e packed = NotPacked) { // 将文件指针重置到文件头 infile.clear(std::ios::goodbit); infile.seekg(std::ios::beg); std::string tar_str; if (d_type == NodeData) tar_str = "$NodeData"; else if (d_type == ElemData) tar_str = "$ElementData"; else throw std::runtime_error("Invalid mesh data type. From gctl::read_gmsh_data(...)"); int tmp_int, data_size; std::string tmp_str; std::stringstream tmp_ss; std::vector tmp_data; std::vector tmp_index; while(getline(infile, tmp_str)) { if (tmp_str == tar_str) { //先读入元素块的名称 添加到数组 for (int i = 0; i < 2; i++) getline(infile, tmp_str); tmp_str.erase(0, 1); // 删除第一个引号 tmp_str.erase(tmp_str.end() - 1); // 删除末尾的引号 out_name.push_back(tmp_str); //跳过元素属性前面的值 最后一次为当前元素块的个数 for (int i = 0; i < 6; i++) getline(infile, tmp_str); gctl::str2ss(tmp_str, tmp_ss); tmp_ss >> data_size; tmp_data.clear(); tmp_data.resize(data_size, 0.0); if(out_index != nullptr) { tmp_index.clear(); tmp_index.resize(data_size); for (int i = 0; i < data_size; i++) { getline(infile, tmp_str); gctl::str2ss(tmp_str, tmp_ss); tmp_ss >> tmp_index[i] >> tmp_data[i]; } if (packed == NotPacked) { for (size_t i = 0; i < data_size; i++) { tmp_index[i] -= 1; } } out_data.push_back(tmp_data); out_index->push_back(tmp_index); } else { for (int i = 0; i < data_size; i++) { getline(infile,tmp_str); gctl::str2ss(tmp_str, tmp_ss); tmp_ss >> tmp_int >> tmp_data[i]; } out_data.push_back(tmp_data); } } } return; } /** * @brief Save Gmsh node block. * * @warning This function is designed for internal usage. Don't call this function directly. * * @tparam A Attribute type of the vertex * @param outfile Output file stream * @param node_x Pointer of the node array * @param node_size Size of the node array * @param packed Whether the nodes' indexes start from zero (Packed) or one (NotPacked) * @param output_tag Whether to output indexed vertex. A vertex will not be output if the tag is false. * Note that passing a output_tag array will reset index of associated vertexes. Use this will caution. */ template void save2gmsh_node(std::ofstream &outfile, vertex *node_x, int node_size, index_packed_e packed = Packed, bool *output_tag = nullptr) { // 将文件指针重置到文件尾 outfile.clear(std::ios::goodbit); outfile.seekp(0, std::ios::end); // it is better to set the first vertex index to 1 to avoid a display bug in Gmsh if (packed == Packed) { if (output_tag != nullptr) { int valid_count = 0; for (int i = 0; i < node_size; i++) { if (output_tag[i]) valid_count++; } int valid_id = 0; outfile << "$Nodes" << std::endl << valid_count << std::endl; for (int i = 0; i < node_size; i++) { if (output_tag[i]) { node_x[i].id = valid_id; valid_id++; outfile << node_x[i].id << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14) << node_x[i].x << " " << node_x[i].y << " 0.0" << std::endl; } } } else { outfile << "$Nodes" << std::endl << node_size << std::endl; for (int i = 0; i < node_size; i++) { outfile << node_x[i].id << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14) << node_x[i].x << " " << node_x[i].y << " 0.0" << std::endl; } } } else { if (output_tag != nullptr) { int valid_count = 0; for (int i = 0; i < node_size; i++) { if (output_tag[i]) valid_count++; } int valid_id = 0; outfile << "$Nodes" << std::endl << valid_count << std::endl; for (int i = 0; i < node_size; i++) { if (output_tag[i]) { node_x[i].id = valid_id; valid_id++; outfile << node_x[i].id + 1 << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14) << node_x[i].x << " " << node_x[i].y << " 0.0" << std::endl; } } } else { outfile << "$Nodes" << std::endl << node_size << std::endl; for (int i = 0; i < node_size; i++) { outfile << node_x[i].id + 1 << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14) << node_x[i].x << " " << node_x[i].y << " 0.0" << std::endl; } } } outfile<<"$EndNodes"< void save2gmsh_node(std::ofstream &outfile, vertex *node_x, int node_size, index_packed_e packed = Packed, bool *output_tag = nullptr) { // 将文件指针重置到文件尾 outfile.clear(std::ios::goodbit); outfile.seekp(0, std::ios::end); // it is better to set the first vertex index to 1 to avoid a display bug in Gmsh if (packed == Packed) { if (output_tag != nullptr) { int valid_count = 0; for (int i = 0; i < node_size; i++) { if (output_tag[i]) valid_count++; } int valid_id = 0; outfile << "$Nodes" << std::endl << valid_count << std::endl; for (int i = 0; i < node_size; i++) { if (output_tag[i]) { node_x[i].id = valid_id; valid_id++; outfile << node_x[i].id << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14) << node_x[i].x << " " << node_x[i].y << " " << node_x[i].z << std::endl; } } } else { outfile << "$Nodes" << std::endl << node_size << std::endl; for (int i = 0; i < node_size; i++) { outfile << node_x[i].id << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14) << node_x[i].x << " " << node_x[i].y << " " << node_x[i].z << std::endl; } } } else { if (output_tag != nullptr) { int valid_count = 0; for (int i = 0; i < node_size; i++) { if (output_tag[i]) valid_count++; } int valid_id = 0; outfile << "$Nodes" << std::endl << valid_count << std::endl; for (int i = 0; i < node_size; i++) { if (output_tag[i]) { node_x[i].id = valid_id; valid_id++; outfile << node_x[i].id + 1 << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14) << node_x[i].x << " " << node_x[i].y << " " << node_x[i].z << std::endl; } } } else { outfile << "$Nodes" << std::endl << node_size << std::endl; for (int i = 0; i < node_size; i++) { outfile << node_x[i].id + 1 << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14) << node_x[i].x << " " << node_x[i].y << " " << node_x[i].z << std::endl; } } } outfile << "$EndNodes" << std::endl; return; } /** * @brief Save 2D/3D meshes to a Gmsh's mesh file. * * @param[in] outfile Output file stream. * @param[in] node_x The vertex2dc array of nodes' coordinates. * @param[in] node_size The number of node. * @param[in] ele_index The triangle2d array of element's index. * @param[in] ele_size The number of element. * @param[in] pack Indicates whether to set the starting index of nodes to zero. The * node's ordering will start with one if this option is false. The default value of this * variable is true. * * @return status of the function. */ template void save2gmsh(std::ofstream &outfile, vertex *node_x, int node_size, const type_triangle2d *ele_index, int ele_size, index_packed_e packed = Packed) { // save head info // 将文件指针重置到文件头 保险一点 outfile.clear(std::ios::goodbit); outfile.seekp(std::ios::beg); outfile << "$MeshFormat" << std::endl << "2.2 0 8" << std::endl << "$EndMeshFormat "<id; } outfile << std::endl; } } else { for (int i = 0; i < ele_size; i++) { outfile << i + 1 << " 2 0"; for (int j = 0; j < 3; j++) { outfile << " " << ele_index[i].vert[j]->id + 1; } outfile << std::endl; } } outfile << "$EndElements"<< std::endl; return; } /** * @brief Save 2D/3D meshes to a Gmsh's mesh file. * * @param[in] outfile Output file stream. * @param[in] node_x The vertex2dc array of nodes' coordinates. * @param[in] node_size The number of node. * @param[in] ele_index The triangle2d2o array of element's index. * @param[in] ele_size The number of element. * @param[in] pack Indicates whether to set the starting index of nodes to zero. The * node's ordering will start with one if this option is false. The default value of this * variable is true. * * @return status of the function. */ template void save2gmsh(std::ofstream &outfile, vertex *node_x, int node_size, const type_triangle2d2o *ele_index, int ele_size, index_packed_e packed = Packed) { // save head info // 将文件指针重置到文件头 保险一点 outfile.clear(std::ios::goodbit); outfile.seekp(std::ios::beg); outfile << "$MeshFormat" << std::endl << "2.2 0 8" << std::endl << "$EndMeshFormat "<id; } outfile << " " << ele_index[i].vert[5]->id; outfile << " " << ele_index[i].vert[3]->id; outfile << " " << ele_index[i].vert[4]->id; outfile << std::endl; } } else { for (int i = 0; i < ele_size; i++) { outfile << i + 1 << " 9 0"; for (int j = 0; j < 3; j++) { outfile << " " << ele_index[i].vert[j]->id + 1; } outfile << " " << ele_index[i].vert[5]->id + 1; outfile << " " << ele_index[i].vert[3]->id + 1; outfile << " " << ele_index[i].vert[4]->id + 1; outfile << std::endl; } } outfile << "$EndElements"<< std::endl; return; } template void save2gmsh(std::ofstream &outfile, vertex *node_x, int node_size, const type_rectangle2d *ele_index, int ele_size, index_packed_e packed = Packed) { // save head info // 将文件指针重置到文件头 保险一点 outfile.clear(std::ios::goodbit); outfile.seekp(std::ios::beg); outfile << "$MeshFormat" << std::endl << "2.2 0 8" << std::endl << "$EndMeshFormat "<id; } outfile << std::endl; } } else { for (int i = 0; i < ele_size; i++) { outfile << i + 1 << " 3 0"; for (int j = 0; j < 4; j++) { outfile << " " << ele_index[i].vert[j]->id + 1; } outfile << std::endl; } } outfile << "$EndElements"<< std::endl; return; } template void save2gmsh(std::ofstream &outfile, vertex *node_x, int node_size, const type_triangle *ele_index, int ele_size, index_packed_e packed = Packed, bool *out_ele_tag = nullptr, bool *out_node_tag = nullptr) { // Set the file stream to the head outfile.clear(std::ios::goodbit); outfile.seekp(std::ios::beg); // Output head info outfile << "$MeshFormat\n2.2 0 8\n$EndMeshFormat\n"; // Count for valid output elements if out_ele_tag is not nullptr if (out_ele_tag != nullptr && out_node_tag != nullptr) { array index_backup(node_size); // Backup nodes' indexes for (int i = 0; i < node_size; i++) { index_backup[i] = node_x[i].id; } array valid_tag(node_size, false); for (size_t i = 0; i < node_size; i++) { valid_tag[i] = out_node_tag[i]; } for (int i = 0; i < ele_size; i++) { if (!valid_tag[i]) { for (int j = 0; j < 3; j++) { valid_tag[ele_index[i].vert[j]->id] = false; } } } // Save nodes save2gmsh_node(outfile, node_x, node_size, packed, valid_tag.get()); // Save elements int valid_ele_count = 0; for (int i = 0; i < ele_size; i++) { if (out_ele_tag[i]) { valid_ele_count++; } } int valid_id = 0; outfile << "$Elements" << std::endl << valid_ele_count << std::endl; if (packed == Packed) { for (int i = 0; i < ele_size; i++) { if (out_ele_tag[i]) { outfile << valid_id << " 2 0"; valid_id++; for (int j = 0; j < 3; j++) { outfile << " " << ele_index[i].vert[j]->id; } outfile << std::endl; } } } else { for (int i = 0; i < ele_size; i++) { if (out_ele_tag[i]) { outfile << valid_id + 1 << " 2 0"; valid_id++; for (int j = 0; j < 3; j++) { outfile << " " << ele_index[i].vert[j]->id + 1; } outfile << std::endl; } } } outfile << "$EndElements" << std::endl; // Restore nodes' indexes for (int i = 0; i < node_size; i++) { node_x[i].id = index_backup[i]; } } else if (out_ele_tag != nullptr) { array index_backup(node_size); // Backup nodes' indexes for (int i = 0; i < node_size; i++) { index_backup[i] = node_x[i].id; } array valid_tag(node_size, false); for (int i = 0; i < ele_size; i++) { if (out_ele_tag[i]) { for (int j = 0; j < 3; j++) { valid_tag[ele_index[i].vert[j]->id] = true; } } } // Save nodes save2gmsh_node(outfile, node_x, node_size, packed, valid_tag.get()); // Save elements int valid_ele_count = 0; for (int i = 0; i < ele_size; i++) { if (out_ele_tag[i]) { valid_ele_count++; } } int valid_id = 0; outfile << "$Elements" << std::endl << valid_ele_count << std::endl; if (packed == Packed) { for (int i = 0; i < ele_size; i++) { if (out_ele_tag[i]) { outfile << valid_id << " 2 0"; valid_id++; for (int j = 0; j < 3; j++) { outfile << " " << ele_index[i].vert[j]->id; } outfile << std::endl; } } } else { for (int i = 0; i < ele_size; i++) { if (out_ele_tag[i]) { outfile << valid_id + 1 << " 2 0"; valid_id++; for (int j = 0; j < 3; j++) { outfile << " " << ele_index[i].vert[j]->id + 1; } outfile << std::endl; } } } outfile << "$EndElements" << std::endl; // Restore nodes' indexes for (int i = 0; i < node_size; i++) { node_x[i].id = index_backup[i]; } } else if (out_node_tag != nullptr) { array index_backup(node_size); // Backup nodes' indexes for (int i = 0; i < node_size; i++) { index_backup[i] = node_x[i].id; } // Save nodes save2gmsh_node(outfile, node_x, node_size, packed, out_node_tag); // Save elements outfile << "$Elements" << std::endl << ele_size << std::endl; if (packed == Packed) { for (int i = 0; i < ele_size; i++) { outfile << i << " 2 0"; for (int j = 0; j < 3; j++) { outfile << " " << ele_index[i].vert[j]->id; } outfile << std::endl; } } else { for (int i = 0; i < ele_size; i++) { outfile << i + 1 << " 2 0"; for (int j = 0; j < 3; j++) { outfile << " " << ele_index[i].vert[j]->id + 1; } outfile << std::endl; } } outfile << "$EndElements" << std::endl; // Restore nodes' indexes for (int i = 0; i < node_size; i++) { node_x[i].id = index_backup[i]; } } else { // Save nodes save2gmsh_node(outfile, node_x, node_size, packed); // Save elements outfile << "$Elements" << std::endl << ele_size << std::endl; if (packed == Packed) { for (int i = 0; i < ele_size; i++) { outfile << i << " 2 0"; for (int j = 0; j < 3; j++) { outfile << " " << ele_index[i].vert[j]->id; } outfile << std::endl; } } else { for (int i = 0; i < ele_size; i++) { outfile << i + 1 << " 2 0"; for (int j = 0; j < 3; j++) { outfile << " " << ele_index[i].vert[j]->id + 1; } outfile << std::endl; } } outfile << "$EndElements" << std::endl; } return; } template void save2gmsh(std::ofstream &outfile, vertex *node_x, int node_size, const type_tetrahedron *ele_index, int ele_size, index_packed_e packed = Packed, bool *output_tag = nullptr) { // Set the file stream to the head outfile.clear(std::ios::goodbit); outfile.seekp(std::ios::beg); // Output head info outfile << "$MeshFormat\n2.2 0 8\n$EndMeshFormat\n"; // Count for valid output elements if output_tag is not nullptr if (output_tag != nullptr) { array index_backup(node_size); // Backup nodes' indexes for (int i = 0; i < node_size; i++) { index_backup[i] = node_x[i].id; } array valid_tag(node_size, false); for (int i = 0; i < ele_size; i++) { if (output_tag[i]) { for (int j = 0; j < 3; j++) { valid_tag[ele_index[i].vert[j]->id] = true; } } } // Save nodes save2gmsh_node(outfile, node_x, node_size, packed, valid_tag.get()); // Save elements int valid_ele_count = 0; for (int i = 0; i < ele_size; i++) { if (output_tag[i]) { valid_ele_count++; } } int valid_id = 0; outfile << "$Elements" << std::endl << valid_ele_count << std::endl; if (packed == Packed) { for (int i = 0; i < ele_size; i++) { if (output_tag[i]) { outfile << valid_id << " 4 0"; valid_id++; for (int j = 0; j < 4; j++) { outfile << " " << ele_index[i].vert[j]->id; } outfile << std::endl; } } } else { for (int i = 0; i < ele_size; i++) { if (output_tag[i]) { outfile << valid_id + 1 << " 4 0"; valid_id++; for (int j = 0; j < 4; j++) { outfile << " " << ele_index[i].vert[j]->id + 1; } outfile << std::endl; } } } outfile << "$EndElements"<< std::endl; // Restore nodes' indexes for (int i = 0; i < node_size; i++) { node_x[i].id = index_backup[i]; } } else { // save node save2gmsh_node(outfile, node_x, node_size, packed); // save elements outfile << "$Elements" << std::endl << ele_size << std::endl; if (packed == Packed) { for (int i = 0; i < ele_size; i++) { outfile << i << " 4 0"; for (int j = 0; j < 4; j++) { outfile << " " << ele_index[i].vert[j]->id; } outfile << std::endl; } } else { for (int i = 0; i < ele_size; i++) { outfile << i + 1 << " 4 0"; for (int j = 0; j < 4; j++) { outfile << " " << ele_index[i].vert[j]->id + 1; } outfile << std::endl; } } outfile << "$EndElements"<< std::endl; } return; } template void save2gmsh(std::ofstream &outfile, vertex *node_x, int node_size, const type_block *ele_index, int ele_size, index_packed_e packed = Packed) { // save head info // 将文件指针重置到文件头 保险一点 outfile.clear(std::ios::goodbit); outfile.seekp(std::ios::beg); outfile << "$MeshFormat" << std::endl << "2.2 0 8" << std::endl << "$EndMeshFormat "<id; } outfile << std::endl; } } else { for (int i = 0; i < ele_size; i++) { outfile << i + 1 << " 5 0"; for (int j = 0; j < 8; j++) { outfile << " " << ele_index[i].vert[j]->id + 1; } outfile << std::endl; } } outfile << "$EndElements"<< std::endl; return; } template void save2gmsh(std::ofstream &outfile, vertex *node_x, int node_size, const type_tricone *ele_index, int ele_size, index_packed_e packed = Packed) { // save head info // 将文件指针重置到文件头 保险一点 outfile.clear(std::ios::goodbit); outfile.seekp(std::ios::beg); outfile << "$MeshFormat" << std::endl << "2.2 0 8" << std::endl << "$EndMeshFormat "<id; } outfile << std::endl; } } else { for (int i = 0; i < ele_size; i++) { outfile << i + 1 << " 2 0"; for (int j = 0; j < 3; j++) { outfile << " " << ele_index[i].vert[j]->id + 1; } outfile << std::endl; } } outfile << "$EndElements"<< std::endl; return; } template void save2gmsh(std::ofstream &outfile, vertex *node_x, int node_size, const type_prism *ele_index, int ele_size, index_packed_e packed = Packed) { // save head info // 将文件指针重置到文件头 保险一点 outfile.clear(std::ios::goodbit); outfile.seekp(std::ios::beg); outfile << "$MeshFormat" << std::endl << "2.2 0 8" << std::endl << "$EndMeshFormat "<id; } outfile << std::endl; } } else { for (int i = 0; i < ele_size; i++) { outfile << i + 1 << " 6 0"; for (int j = 0; j < 6; j++) { outfile << " " << ele_index[i].vert[j]->id + 1; } outfile << std::endl; } } outfile << "$EndElements"<< std::endl; return; } template void save2gmsh(std::ofstream &outfile, vertex *node_x, int node_size, const type_tesseroid *ele_index, int ele_size, index_packed_e packed = Packed) { // save head info // 将文件指针重置到文件头 保险一点 outfile.clear(std::ios::goodbit); outfile.seekp(std::ios::beg); outfile << "$MeshFormat" << std::endl << "2.2 0 8" << std::endl << "$EndMeshFormat "<id; } outfile << std::endl; } } else { for (int i = 0; i < ele_size; i++) { outfile << i + 1 << " 5 0"; for (int j = 0; j < 8; j++) { outfile << " " << ele_index[i].vert[j]->id + 1; } outfile << std::endl; } } outfile << "$EndElements"<< std::endl; return; } template void save2gmsh(std::ofstream &outfile, const type_tetrahedron *ele_index, int ele_size, index_packed_e packed = Packed) { // save head info // 将文件指针重置到文件头 保险一点 outfile.clear(std::ios::goodbit); outfile.seekp(std::ios::beg); outfile << "$MeshFormat" << std::endl << "2.2 0 8" << std::endl << "$EndMeshFormat "< node_index; node_index.reserve(4*ele_size); for (int i = 0; i < ele_size; ++i) { for (int j = 0; j < 4; ++j) { node_index.push_back(ele_index[i].vert[j]); } } std::vector::iterator pos; std::sort(node_index.begin(), node_index.end()); //对顶点序列由小到大排序 pos = std::unique(node_index.begin(), node_index.end()); //获取重复序列开始的位置 node_index.erase(pos, node_index.end()); //删除重复点 outfile << "$Nodes" << std::endl << node_index.size() << std::endl; // it is better to set the first vertex index to 1 to avoid a display bug in Gmsh if (packed == Packed) { for (int i = 0; i < node_index.size(); i++) { outfile << node_index[i]->id << " " << std::setprecision(16) << node_index[i]->x << " " << node_index[i]->y << " " << node_index[i]->z << std::endl; } } else { for (int i = 0; i < node_index.size(); i++) { outfile << node_index[i]->id + 1 << " " << std::setprecision(16) << node_index[i]->x << " " << node_index[i]->y << " " << node_index[i]->z << std::endl; } } outfile<<"$EndNodes"<id; } outfile << std::endl; } } else { for (int i = 0; i < ele_size; i++) { outfile << i + 1 << " 4 0"; for (int j = 0; j < 4; j++) { outfile << " " << ele_index[i].vert[j]->id + 1; } outfile << std::endl; } } outfile << "$EndElements"<< std::endl; return; } /** * @brief Save 2D/3D meshes to Gmsh .msh files. * * @param outfile Output file stream. * @param[in] element Output element array * @param[in] node Output vertice array * @param[in] packed Indicates whether to set the starting index to zero. The * node and element's ordering will start with one if this option is false. * The default value of this variable is true. */ template void save2gmsh(std::ofstream &outfile, const array> &element, const array> &node, index_packed_e packed = Packed) { save2gmsh(outfile, node.get(), node.size(), element.get(), element.size(), packed); return; } template void save2gmsh(std::ofstream &outfile, const array> &element, const array> &node, index_packed_e packed = Packed) { save2gmsh(outfile, node.get(), node.size(), element.get(), element.size(), packed); return; } template void save2gmsh(std::ofstream &outfile, const array> &element, const array> &node, index_packed_e packed = Packed) { save2gmsh(outfile, node.get(), node.size(), element.get(), element.size(), packed); return; } template void save2gmsh(std::ofstream &outfile, const array> &element, const array> &node, index_packed_e packed = Packed, array *out_ele_tag = nullptr, array *out_node_tag = nullptr) { if (out_ele_tag != nullptr && out_node_tag != nullptr) { if (element.size() != out_ele_tag->size() || node.size() != out_node_tag->size()) { throw gctl::runtime_error("Incompatible tag size. From save2gmsh(...)"); return; } save2gmsh(outfile, node.get(), node.size(), element.get(), element.size(), packed, out_ele_tag->get(), out_node_tag->get()); } else if (out_ele_tag != nullptr) { if (element.size() != out_ele_tag->size()) { throw gctl::runtime_error("Incompatible tag size. From save2gmsh(...)"); return; } save2gmsh(outfile, node.get(), node.size(), element.get(), element.size(), packed, out_ele_tag->get()); } else if (out_node_tag != nullptr) { if (node.size() != out_node_tag->size()) { throw gctl::runtime_error("Incompatible tag size. From save2gmsh(...)"); return; } save2gmsh(outfile, node.get(), node.size(), element.get(), element.size(), packed, nullptr, out_node_tag->get()); } else { save2gmsh(outfile, node.get(), node.size(), element.get(), element.size(), packed); } return; } template void save2gmsh(std::ofstream &outfile, const array> &element, const array> &node, index_packed_e packed = Packed, array *output_tag = nullptr) { if (output_tag != nullptr) { if (element.size() != output_tag->size()) { throw gctl::runtime_error("Incompatible tag size. From save2gmsh(...)"); return; } save2gmsh(outfile, node.get(), node.size(), element.get(), element.size(), packed, output_tag->get()); } else { save2gmsh(outfile, node.get(), node.size(), element.get(), element.size(), packed); } return; } template void save2gmsh(std::ofstream &outfile, const array> &element, const array> &node, index_packed_e packed = Packed) { save2gmsh(outfile, node.get(), node.size(), element.get(), element.size(), packed); return; } template void save2gmsh(std::ofstream &outfile, const array> &element, const array> &node, index_packed_e packed = Packed) { save2gmsh(outfile, node.get(), node.size(), element.get(), element.size(), packed); return; } template void save2gmsh(std::ofstream &outfile, const array> &element, const array> &node, index_packed_e packed = Packed) { save2gmsh(outfile, node.get(), node.size(), element.get(), element.size(), packed); return; } template void save2gmsh(std::ofstream &outfile, const array> &element, const array> &node, index_packed_e packed = Packed) { save2gmsh(outfile, node.get(), node.size(), element.get(), element.size(), packed); return; } template void save2gmsh(std::ofstream &outfile, const array> &element, index_packed_e packed = Packed) { save2gmsh(outfile, element.get(), element.size(), packed); return; } /** * @brief Save a Gmsh data block to a given file. * * @param[in] filename The filename of the file that in_data is going to be added into. * @param[in] dataname Name of the data that is going to be saved. * @param[in] in_data Pointer of the double array of the input data. * @param[in] d_size Number of the input data. * @param[in] in_index Pointer of the int array of the input data's index. The size of in_index * must be equal to in_data. * @param[in] data_type The data type to be save. This enum could be equals to NODE_DATA * or ELEMENT_DATA. * @param[in] pack Indicates whether to set the starting index of data to zero. * The data ordering will start with one if this option is false. The default value of * this variable is true. * * @return status of the function */ template void save_gmsh_data(std::ofstream &outfile, std::string dataname, const T *in_data, int d_size, mesh_data_type_e datatype, index_packed_e packed = Packed, const size_t *in_index = nullptr) { if (in_data == nullptr) { throw runtime_error("Null data pointer. From void gctl::save_gmsh_data(...)"); } if (d_size <= 0) { throw runtime_error("Invalid array size. From void gctl::save_gmsh_data(...)"); } // 将文件指针重置到文件尾 outfile.clear(std::ios::goodbit); outfile.seekp(0, std::ios::end); if (datatype == NodeData) outfile<<"$NodeData"< void save_gmsh_data(std::ofstream &outfile, std::string dataname, const array &in_data, mesh_data_type_e datatype, index_packed_e packed = Packed, const array *in_index = nullptr) { if (in_index != nullptr) { save_gmsh_data(outfile, dataname, in_data.get(), in_data.size(), datatype, packed, in_index->get()); } else save_gmsh_data(outfile, dataname, in_data.get(), in_data.size(), datatype, packed); return; } /** * @brief 保存Gmsh模型数据单元 * * @param outfile 输出文件流 * @param[in] dataname 模型数据名称 * @param[in] in_data 模型数据数组 * @param[in] datatype 模型数据类型 * @param[in] in_index 模型数据索引数组的指针,为空时则依序储存模型数据数组 * @param[in] pack 输出模型数组索引是否从0开始,为假时索引值从1开始 */ template void save_gmsh_data(std::ofstream &outfile, std::string dataname, const std::vector &in_data, mesh_data_type_e datatype, index_packed_e packed = Packed, const std::vector *in_index = nullptr) { if (in_index != nullptr) { save_gmsh_data(outfile, dataname, in_data.data(), in_data.size(), datatype, packed, in_index->data()); } else save_gmsh_data(outfile, dataname, in_data.data(), in_data.size(), datatype, packed); return; } /** * @brief Save a Gmsh data block to a given file. * * @param[in] filename The filename of the file that in_data is going to be added into. * @param[in] dataname Name of the data that is going to be saved. * @param[in] in_data Pointer of the point3dc array of the input data. * @param[in] d_size Number of the input data. * @param[in] in_index Pointer of the int array of the input data's index. The size of in_index * must be equal to in_data. * @param[in] data_type The data type to be save. This enum could be equals to NODE_DATA * or ELEMENT_DATA. * @param[in] pack Indicates whether to set the starting index of data to zero. * The data ordering will start with one if this option is false. The default value of * this variable is true. * * @return status of the function */ template void save_gmsh_data(std::ofstream &outfile, std::string dataname, const point3c *in_data, int d_size, mesh_data_type_e datatype, index_packed_e packed = Packed, const size_t *in_index = nullptr) { if (in_data == nullptr) { throw runtime_error("Null data pointer. From void gctl::save_gmsh_data(...)"); } if (d_size <= 0) { throw runtime_error("Invalid array size. From void gctl::save_gmsh_data(...)"); } // 将文件指针重置到文件尾 outfile.clear(std::ios::goodbit); outfile.seekp(0, std::ios::end); if (datatype == NodeData) outfile<<"$NodeData"< void save_gmsh_data(std::ofstream &outfile, std::string dataname, const array> &in_data, mesh_data_type_e datatype, index_packed_e packed = Packed, const array *in_index = nullptr) { if (in_index != nullptr) { save_gmsh_data(outfile, dataname, in_data.get(), in_data.size(), datatype, packed, in_index->get()); } else save_gmsh_data(outfile, dataname, in_data.get(), in_data.size(), datatype, packed); return; } /** * @brief 保存Gmsh模型数据单元 * * @param outfile 输出文件流 * @param[in] dataname 模型数据名称 * @param[in] in_data 模型数据数组 * @param[in] datatype 模型数据类型 * @param[in] in_index 模型数据索引数组的指针,为空时则依序储存模型数据数组 * @param[in] pack 输出模型数组索引是否从0开始,为假时索引值从1开始 */ template void save_gmsh_data(std::ofstream &outfile, std::string dataname, const std::vector> &in_data, mesh_data_type_e datatype, index_packed_e packed = Packed, const std::vector *in_index = nullptr) { if (in_index != nullptr) { save_gmsh_data(outfile, dataname, in_data.data(), in_data.size(), datatype, packed, in_index->data()); } else save_gmsh_data(outfile, dataname, in_data.data(), in_data.size(), datatype, packed); return; } #ifdef GCTL_EIGEN template void save_gmsh_data(std::ofstream &outfile, std::string dataname, const Eigen::Matrix &in_data, mesh_data_type_e datatype, index_packed_e packed = Packed, const Eigen::Matrix *in_index = nullptr) { size_t d_size = in_data.size(); if (d_size <= 0) { throw runtime_error("Invalid array size. From void gctl::save_gmsh_data(...)"); } // 将文件指针重置到文件尾 outfile.clear(std::ios::goodbit); outfile.seekp(0, std::ios::end); if (datatype == NodeData) outfile<<"$NodeData"<coeff(j) << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14) << in_data[j] << std::endl; } } else if (packed == NotPacked && in_index != nullptr) { for (int j = 0; j < d_size; j++) { if (!std::isnan(in_data[j])) outfile << in_index->coeff(j)+1 << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14) << in_data[j] << std::endl; } } else if (packed == Packed && in_index == nullptr) { for (int j = 0; j < d_size; j++) { if (!std::isnan(in_data[j])) outfile << j << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14) << in_data[j] << std::endl; } } else { for (int j = 0; j < d_size; j++) { if (!std::isnan(in_data[j])) outfile << j+1 << " " << std::setiosflags(std::ios::scientific) << std::setprecision(14) << in_data[j] << std::endl; } } if (datatype == NodeData) outfile << "$EndNodeData" << std::endl; else outfile << "$EndElementData"<< std::endl; return; } #endif // GCTL_EIGEN } #endif //_GCTL_GMSH_IO_H