/******************************************************** * ██████╗ ██████╗████████╗██╗ * ██╔════╝ ██╔════╝╚══██╔══╝██║ * ██║ ███╗██║ ██║ ██║ * ██║ ██║██║ ██║ ██║ * ╚██████╔╝╚██████╗ ██║ ███████╗ * ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝ * Geophysical Computational Tools & Library (GCTL) * * Copyright (c) 2022 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. ******************************************************/ // add gctl head files #include "gctl/core.h" #include "gctl/io.h" #include "gctl/utility.h" int main(int argc, char *argv[]) try { gctl::flags_parser fp; fp.set_proname("tetgen2gmsh"); fp.set_proinfo("Convert Tetgen's files to Gmsh's (.msh) file. This program is a toolkit of the GCTL package. The GCTL comes with ABSOLUTE NO WARRANTY. \ Please see instructions or contact the author for more information."); fp.add_opt('t', "tetgen", required_argument, NULL, "Tetgen's mesh files. To run the program correctly, one must at least have both .node and .ele files. \ NOTE: name extensions are not needed.", "", true); fp.add_opt('g', "gmsh", required_argument, NULL, "Gmsh's (.msh) file. The input Tetgen's file name will be used if the -g option is not set. \ NOTE: name extensions are not needed.", "", false); fp.add_opt('n', "not-packed", no_argument, NULL, "The index of the input nodes and elements are not packed (starting from one).", 0, false); fp.add_opt('a', "attribute", required_argument, NULL, "Extract attributes of the nodes, faces or elements. Use 'n' for nodes, 'f' for faces and 'e' for elements.", "nfe", false); fp.add_opt('p', "physics", required_argument, NULL, "Physical groups' tag and name. Separated by commas", "//,...", false); fp.add_opt('h', "help", no_argument, NULL, "Show help information.", 0, false); fp.configure(argc, argv); if (argc == 1 || fp.set_opt('h')) { fp.show_help_page(); return 0; } std::string in_name, out_name, attri_str, phys_str; fp.get_argv({'t', 'g', 'a', 'p'}, {&in_name, &out_name, &attri_str, &phys_str}); // 查看是否通过强制参数检查 if (!fp.pass_mandatory()) return 0; if (out_name == "NULL") out_name = in_name; gctl::index_packed_e file_packed = gctl::Packed; if (fp.set_opt('n')) file_packed = gctl::NotPacked; bool get_nt = false, get_ft = false, get_et = false; if (attri_str != "NULL") { if (attri_str.find('n') != std::string::npos) get_nt = true; if (attri_str.find('f') != std::string::npos) get_ft = true; if (attri_str.find('e') != std::string::npos) get_et = true; } gctl::array tetgen_phys; gctl::array geo_tag; if (phys_str != "NULL") { std::vector phys_pairs; gctl::parse_string_to_vector(phys_str, ',', phys_pairs); tetgen_phys.resize(phys_pairs.size()); geo_tag.resize(phys_pairs.size()); for (size_t i = 0; i < phys_pairs.size(); i++) { tetgen_phys[i].phys_tag = i+1; // Assign pyhsical group tag automatically gctl::parse_string_to_value(phys_pairs[i], '/', true, tetgen_phys[i].dim_tag, geo_tag[i], tetgen_phys[i].name); } } // declare arrays here gctl::array tetgen_node; gctl::array tetgen_face; gctl::array tetgen_ele; gctl::array node_tag, face_tag, ele_tag; gctl::matrix face_attri, ele_attri; if (get_nt) { gctl::read_Tetgen_node(in_name, tetgen_node, file_packed, &node_tag); } else gctl::read_Tetgen_node(in_name, tetgen_node, file_packed); if (get_et) { gctl::read_Tetgen_element(in_name, tetgen_ele, tetgen_node, file_packed, &ele_tag); ele_attri.resize(ele_tag.size(), 2, 0); for (size_t i = 0; i < ele_tag.size(); i++) { ele_attri[i][1] = ele_tag[i]; for (size_t j = 0; j < geo_tag.size(); j++) { if (tetgen_phys[j].dim_tag == 3 && geo_tag[j] == ele_tag[i]) { ele_attri[i][0] = tetgen_phys[j].phys_tag; break; } } } } else gctl::read_Tetgen_element(in_name, tetgen_ele, tetgen_node, file_packed); // try to read face file bool has_face = false; std::string face_name = in_name + ".face"; if (access(face_name.c_str(), 4) != -1) has_face = true; if (get_ft && !has_face) { throw gctl::runtime_error(face_name + " not found or can't be read."); } if (has_face) { if (get_ft) { gctl::read_Tetgen_face(in_name, tetgen_face, tetgen_node, file_packed, &face_tag); face_attri.resize(face_tag.size(), 2, 0); for (size_t i = 0; i < face_tag.size(); i++) { face_attri[i][1] = face_tag[i]; for (size_t j = 0; j < geo_tag.size(); j++) { if (tetgen_phys[j].dim_tag == 2 && geo_tag[j] == face_tag[i]) { face_attri[i][0] = tetgen_phys[j].phys_tag; break; } } } } else gctl::read_Tetgen_face(in_name, tetgen_face, tetgen_node, file_packed); } gctl::gmshio gio; gio.init_file(out_name, gctl::Output); gio.set_packed(gctl::NotPacked, gctl::Output); gctl::array fdata_index, edata_index; if (has_face && get_ft) gio.element_register(tetgen_face, &face_attri, &fdata_index); else if (has_face) gio.element_register(tetgen_face, nullptr, &fdata_index); if (get_et) gio.element_register(tetgen_ele, &ele_attri, &edata_index); else gio.element_register(tetgen_ele, nullptr, &edata_index); if (!tetgen_phys.empty()) gio.save_registered_mesh(tetgen_node, &tetgen_phys); else gio.save_registered_mesh(tetgen_node); if (get_nt) gio.save_data("Node Tag", node_tag, gctl::NodeData); if (get_ft && has_face) gio.save_data("Face Tag", face_tag, gctl::ElemData, &fdata_index); if (get_et) gio.save_data("Element Tag", ele_tag, gctl::ElemData, &edata_index); return 0; } catch(std::exception &e) { GCTL_ShowWhatError(e.what(), GCTL_ERROR_ERROR, 0, 0, 0); }