179 lines
6.9 KiB
C++
179 lines
6.9 KiB
C++
|
/********************************************************
|
||
|
* ██████╗ ██████╗████████╗██╗
|
||
|
* ██╔════╝ ██╔════╝╚══██╔══╝██║
|
||
|
* ██║ ███╗██║ ██║ ██║
|
||
|
* ██║ ██║██║ ██║ ██║
|
||
|
* ╚██████╔╝╚██████╗ ██║ ███████╗
|
||
|
* ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝
|
||
|
* 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);
|
||
|
}
|