gctl_toolkits/tetgen2gmsh/tetgen2gmsh.cpp

179 lines
6.9 KiB
C++
Raw Permalink Normal View History

2024-09-10 20:25:18 +08:00
/********************************************************
*
*
*
*
*
*
* 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 <http://www.gnu.org/licenses/>.
*
* 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.", "<filename>", 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.", "<filename>", 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", "<dim>/<geo-tag>/<name>,...", 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<gctl::gmsh_physical_group> tetgen_phys;
gctl::array<int> geo_tag;
if (phys_str != "NULL")
{
std::vector<std::string> 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<gctl::vertex3dc> tetgen_node;
gctl::array<gctl::triangle> tetgen_face;
gctl::array<gctl::tetrahedron> tetgen_ele;
gctl::array<int> node_tag, face_tag, ele_tag;
gctl::matrix<int> 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<size_t> 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);
}