move mesh_io to mesh

This commit is contained in:
张壹 2025-04-23 17:05:28 +08:00
parent f18ad0c6cf
commit c647ae37e9
4 changed files with 1 additions and 2760 deletions

View File

@ -41,7 +41,6 @@
#include "io/tetgen_io.h"
#include "io/triangle_io.h"
#include "io/gmsh_io.h"
#include "io/mesh_io.h"
#include "io/text_io.h"
#include "io/dsv_io.h"

View File

@ -58,7 +58,7 @@ namespace gctl
};
/**
* @brief Gmsh文件的IO类 使mesh_io类型替代
* @brief Gmsh文件的IO类
*/
class gmshio
{

File diff suppressed because it is too large Load Diff

View File

@ -1,734 +0,0 @@
/********************************************************
*
*
*
*
*
*
* 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 <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.
******************************************************/
#ifndef _GCTL_MESH_IO_H
#define _GCTL_MESH_IO_H
#include <unordered_set>
#include <map>
#include "../math/refellipsoid.h"
#include "triangle_io.h"
#include "tetgen_io.h"
#include "gmsh_io.h"
namespace gctl
{
/**
* @brief
*/
#define DEFAULT_INVALID_TAG -9999
/**
* @brief
*/
enum element_type_enum
{
NotSet,
_2NodeLine,
_3NodeTriangle,
_4NodeQuadrangle,
_4NodeTetrahedron,
_8NodeHexahedron,
_6NodePrism,
_5NodePyramid,
_3NodeSecondOrderLine,
_6NdoeSecondOrderLine,
_9NodeSecondOrderQuadrangle,
_10NodeSecondOrderTetrahedron,
_27NodeSecondOrderHexahedron,
_18NodeSecondOrderPrism,
_14NodeSecondOrderPyramid,
_1NodePoint,
_8NodeSecondOrderQuadrangle,
_20NdoeSecondOrderHexahedron,
_15NodeSecondOrderPrism,
_13NodeSecondOrderPyramid,
_9NodeThirdOrderIncompleteTriangle,
_10NdoeThirdOrderTriangle,
_12NodeFourthOrderIncompleteTriangle,
_15NodeFourthOrderTriangle,
_15NodeFifthOrderCompleteTriangle,
_21NodeFifthOrderCompleteTriangle,
_4NodeThirdOrderEdge,
_5NodeFourthOrderEdge,
_6NodeFifthOrderEdge,
_20NodeThirdOrderTetrahedron,
_35NodeFourthOrderTetrahedron,
_56NodeFifithOrderTetrahedron,
_64NodeThirdOrderHexahedron,
_125NodeFourthOrderHexahedron,
};
/**
* @brief
*
*/
enum element_tag_enum
{
PhysicalTag, // 元素的物理分组标签
GeometryTag, // 元素的几何分组标签
PartitionTag, // 元素的剖分分组标签
NodeTag, // 顶点的标签(仅用于输出顶点标签数据)
};
/**
* @brief
*
*/
struct meshio_element
{
bool enabled; // 单元体是否有效
int id; // 单元体编号
element_type_enum type; // 单元体类型
array<vertex3dc*> vert_ptrs; // 顶点指针数组
array<meshio_element*> neigh_ptrs; // 相邻单元体指针数组
meshio_element();
};
/**
* @brief
*
*/
struct meshio_data
{
bool enabled; // 数据体是否有效
mesh_data_type_e d_type; // 数据类型
array<std::string> str_tag; // 字符串类型的标签(默认为一个,即为数据的名称)
array<double> real_tag; // 实数类型的标签默认为一个等于0.0
array<int> int_tag; // 整数类型的标签(最少三个,最后一个为数据的长度)
array<void*> tar_ptrs; // 数据连接的对象指针数组 具体类型为vertex3dc*或meshio_element*
array<double> val; // 数据值(目前仅支持标量数据,后续再添加对矢量数据的支持)
meshio_data();
/**
* @brief
*
*/
void clear();
/**
* @brief
*
*/
bool pass_check();
};
/**
* @brief
*
*/
struct meshio_element_group
{
bool enabled; // 组是否有效
element_type_enum type; // 组内单元体类型
int phys_group; // 物理分组标签
int geom_group; // 几何分组标签
int part_group; // 剖分分组标签
std::string name; // 组名
std::vector<meshio_element*> elem_ptrs; // 组内单元体指针数组
meshio_element_group();
/**
* @brief
*
*/
void enable_elements();
/**
* @brief
*
*/
void disable_elements();
};
/**
* @brief
*
*/
class mesh_io
{
public:
mesh_io();
virtual ~mesh_io();
/**
* @brief
*
*/
void reset();
/**
* @brief
*
* @param ss clog
*/
void info(std::ostream &ss = std::clog);
/**
* @brief
*
* @param swt 使Enable或Disable
* @param e_type NotSet
*/
void edit_group(switch_type_e swt, element_type_enum e_type = NotSet);
/**
* @brief
*
* @param swt 使Enable或Disable
* @param grp_name
*/
void edit_group(switch_type_e swt, std::string grp_name);
/**
* @brief
*
* @param swt 使Enable或Disable
* @param tag_type PhysicalTagGeometryTag或者PartitionTag
* @param tag
*/
void edit_group(switch_type_e swt, element_tag_enum tag_type, int tag);
/**
* @brief
*
* @param anchor_type PhysicalTagGeometryTag或者PartitionTag
* @param anchor_group
* @param new_name
*/
void edit_group(element_tag_enum anchor_type, int anchor_group, std::string new_name);
/**
* @brief
*
* @param anchor_type PhysicalTagGeometryTag或者PartitionTag
* @param anchor_group
* @param tar_type PhysicalTagGeometryTag或者PartitionTag
* @param tar_group
*/
void edit_group(element_tag_enum anchor_type, int anchor_group, element_tag_enum tar_type, int tar_group);
/**
* @brief
*
* @param tag_type PhysicalTagGeometryTag或者PartitionTag
* @param group_name
* @return
*/
int group_tag(element_tag_enum tag_type, std::string group_name);
/**
* @brief
*
* @return
*/
const array<vertex3dc> &get_all_nodes();
/**
* @brief
*
* @return
*/
const array<meshio_element> &get_all_elems();
/**
* @brief
*
* @param e_type NotSet
*/
void select_elements(element_type_enum e_type = NotSet);
/**
* @brief
*
* @param tag_type
* @param tag
*/
void select_elements(element_tag_enum tag_type, int tag);
/**
* @brief
*
* @param phys_name
*/
void select_elements(std::string phys_name);
/**
* @brief
*
* @param datname
* @param dtype
*/
void select_elements(std::string dat_name, mesh_data_type_e dtype);
/**
* @brief 使select_elements函数选择
*
* @return
*/
size_t selected_node_size();
/**
* @brief 使select_elements函数选择
*
* @return
*/
size_t selected_element_size();
/**
* @brief -9999
*
* @return
*/
const array<int> &selected_node_tags();
/**
* @brief -9999
*
* @return
*/
const array<int> &selected_element_tags(element_tag_enum tag_type);
/**
* @brief gmsh格式分组表
*
* @param g_groups gmsh格式表
*/
void get_gmsh_physical_groups(std::vector<gmsh_physical_group> &g_groups);
/**
* @brief
*
* @param tag_type
*/
void convert_tags_to_data(element_tag_enum tag_type);
/**
* @brief name的数据
*
* @param name
* @param type
*
* @return -1
*/
int if_saved_data(std::string name, mesh_data_type_e type);
/**
* @brief
*
* @param name
* @param type
* @return
*/
meshio_data &get_data(std::string name, mesh_data_type_e type);
/**
* @brief
*
* @param name
* @param type
* @return
*/
meshio_data *get_data_ptr(std::string name, mesh_data_type_e type);
/**
* @brief
*
* @param name
* @param type
*
* @return
*/
array<double> get_selected_data(std::string name, mesh_data_type_e type);
/**
* @brief
*
* @param data
* @param name
* @param dtype
* @param op OverWrite或Append
*/
void add_data(std::string name, const array<double> &data,
mesh_data_type_e dtype, output_type_e op = OverWrite);
/**
* @brief
*
* @param swt 使Enable或Disable
* @param dataname null
*/
void edit_data(switch_type_e swt, std::string dataname = "null");
/**
* @brief triangle软件输出的网格剖分文件
*
* @param filename .node和.ele文件必须在同一路径下.neigh文件不是必须的
* @param is_packed 0
*/
void read_triangle_ascii(std::string filename, index_packed_e is_packed = Packed);
/**
* @brief tetgen软件输出的网格剖分文件
*
* @param filename .node和.ele文件必须在同一路径下.neigh文件不是必须的
* @param is_packed 0
*/
void read_tetgen_ascii(std::string filename, index_packed_e is_packed = Packed);
/**
* @brief Gmsh软件输出的网格剖分文件v2.2ASCII文件
*
* @param filename
* @param is_packed 0
*/
void read_gmsh_v2_ascii(std::string filename, index_packed_e is_packed = NotPacked);
/**
* @brief Gmsh软件格式的网格剖分文件v2.2ASCII文件
*
* @param filename
* @param is_packed 0
*/
void save_gmsh_v2_ascii(std::string filename, index_packed_e is_packed = NotPacked);
/**
* @brief Paraview软件格式的网格剖分文件
*
* @param filename
*/
void save_vtk_legacy_ascii(std::string filename);
/**
* @brief
*
* @param filename
* @param dataname
* @param out_coor Cartesian或Spherical
* @param refr out_coor为Cartesian时无效
* @param refR out_coor为Cartesian时无效
*/
void save_data_to_xyz(std::string filename, std::string dataname = "null", coordinate_system_e out_coor = Cartesian, double refr = GCTL_Earth_Radius, double refR = GCTL_Earth_Radius);
/**
* @brief
*
* @tparam T
* @param elems
* @param nodes
*/
template <typename T>
void export_selected_to(array<T> &elems, array<vertex3dc> &nodes);
/**
* @brief
*
* @tparam T
* @param elems
* @param nodes
* @param x_id x索引0
* @param y_id y索引1
*
* @note xyz坐标中的对应项分别赋值给二维坐标的xy值{0,1}xoy平面
* {1,0}yox平面{0,2}xoz平面{1,2}yoz平面
*/
template <typename T>
void export_selected_to(array<T> &elems, array<vertex2dc> &nodes, int x_id = 0, int y_id = 1);
/**
* @brief
*
* @tparam T
* @param elems
* @param nodes
*/
template <typename T>
void import_from(const array<T> &elems, const array<vertex3dc> &nodes);
/**
* @brief
*
* @tparam T
* @param elems
* @param nodes
* @param x_id x坐标到三维坐标系统的索引0
* @param y_id y坐标到三维坐标系统的索引1
*
* @note (x,y)(x,y,z){0,1}(x,y)(x,y,0)
* {1,0}(x,y)(y,x,0){0,2}(x,y)(x,0,z){1,2}(x,y)(0,y,z)
*/
template <typename T>
void import_from(const array<T> &elems, const array<vertex2dc> &nodes, int x_id = 0, int y_id = 1);
protected:
bool initialized_; // 类型是否已经初始化完成
// 有效的顶点、单元体和单元体组的数量
size_t valid_node_size_, valid_elem_size_, valid_group_size_;
array<vertex3dc> nodes_; // 网格顶点 当顶点索引为无效值时将不会被输出
array<meshio_element> elems_; // 网格元素
std::vector<meshio_data> datas_; // 网格数据
std::vector<meshio_element_group> groups_; // 网格单元体组
array<int> nodes_tag_; // 顶点标签
array<int> selected_node_tag_; // 被选择的顶点的标签
array<int> selected_elem_tag_; // 被选择的单元体的标签
std::vector<vertex3dc*> selected_nodes_; // 被选择的顶点
std::vector<meshio_element*> selected_elems_; // 被选择的单元体
std::vector<meshio_element_group*> selected_groups_; // 被选择的单元体组
element_type_enum elem_gmshcode2type_[94]; // gmsh的单元体类型数组 数组索引为gmsh的单元体类型码值
element_type_enum elem_vtkcode2type_[14]; // vtk的单元体类型数组 数组索引为vtk的单元体类型码值
std::map<element_type_enum, int> elem_type2gmshcode_; // 单元体类型到gmsh类型码值的映射
std::map<element_type_enum, int> elem_type2vtkcode_; // 单元体类型到vtk类型码值的映射
std::map<element_type_enum, int> elem_type2size_; // 单元体类型到单元体顶点数量的映射
std::map<element_type_enum, std::string> elem_type2name_; // 单元体类型到单元体名称的映射
std::string elem_name(element_type_enum e_type); // 获取单元体名称字符串
int elem_gmsh_code(element_type_enum e_type); // 获取单元体gmsh类型码值
int elem_vtk_code(element_type_enum e_type); // 获取单元体vtk类型码值
int elem_size(element_type_enum e_type); // 获取单元体顶点数量
element_type_enum elem_gmsh_type(int code); // 获取对应gmsh类型码的单元体类型
element_type_enum elem_vtk_type(int code); // 获取对应vtk类型码的单元体类型
void update_indexing(); // 更新索引(对网格的元素进行操作后需调用)
void sort_groups(); // 对单元体组进行梳理(对网格的元素进行操作后需调用)
element_type_enum match_type(const std::type_info &tinfo); // 根据type_info返回单元体类型
};
template <typename T>
void gctl::mesh_io::export_selected_to(array<T> &elems, array<vertex3dc> &nodes)
{
const std::type_info &tinfo = typeid(T);
element_type_enum oe_type = match_type(tinfo);
size_t n = selected_nodes_.size();
size_t s = selected_elems_.size();
std::map<int, int> node_map;
nodes.resize(n);
for (size_t i = 0; i < n; i++)
{
node_map[selected_nodes_[i]->id] = i; // 原网格顶点索引到新网格顶点索引的映射
nodes[i].id = i;
nodes[i].x = selected_nodes_[i]->x;
nodes[i].y = selected_nodes_[i]->y;
nodes[i].z = selected_nodes_[i]->z;
}
int vnum = elem_size(oe_type);
elems.resize(s);
for (size_t i = 0; i < s; i++)
{
if (selected_elems_[i]->type != oe_type)
throw gctl::invalid_argument("[gctl::mesh_io::export_to] The selected element is not " + elem_name(oe_type) + ".");
elems[i].id = i;
for (size_t v = 0; v < vnum; v++)
elems[i].vert[v] = nodes.get(node_map[selected_elems_[i]->vert_ptrs[v]->id]);
}
node_map.clear();
return;
}
template <typename T>
void gctl::mesh_io::export_selected_to(array<T> &elems, array<vertex2dc> &nodes, int x_id, int y_id)
{
const std::type_info &tinfo = typeid(T);
element_type_enum oe_type = match_type(tinfo);
size_t n = selected_nodes_.size();
size_t s = selected_elems_.size();
std::map<int, int> node_map;
nodes.resize(n);
double xyz_ref[3];
for (size_t i = 0; i < n; i++)
{
node_map[selected_nodes_[i]->id] = i; // 原网格顶点索引到新网格顶点索引的映射
nodes[i].id = i;
xyz_ref[0] = selected_nodes_[i]->x;
xyz_ref[1] = selected_nodes_[i]->y;
xyz_ref[2] = selected_nodes_[i]->z;
nodes[i].x = xyz_ref[x_id];
nodes[i].y = xyz_ref[y_id];
}
int vnum = elem_size(oe_type);
elems.resize(s);
for (size_t i = 0; i < s; i++)
{
if (selected_elems_[i]->type != oe_type)
throw gctl::invalid_argument("[gctl::mesh_io::export_to] The selected element is not " + elem_name(oe_type) + ".");
elems[i].id = i;
for (size_t v = 0; v < vnum; v++)
elems[i].vert[v] = nodes.get(node_map[selected_elems_[i]->vert_ptrs[v]->id]);
}
node_map.clear();
return;
}
template <typename T>
void gctl::mesh_io::import_from(const array<T> &elems, const array<vertex3dc> &nodes)
{
reset(); // 重置网格数据
const std::type_info &tinfo = typeid(T);
element_type_enum oe_type = match_type(tinfo);
int vnum = elem_size(oe_type);
valid_node_size_ = nodes.size();
valid_elem_size_ = elems.size();
nodes_.resize(valid_node_size_);
selected_nodes_.resize(valid_node_size_);
for (size_t i = 0; i < valid_node_size_; i++)
{
nodes_[i].id = i;
nodes_[i].x = nodes[i].x;
nodes_[i].y = nodes[i].y;
nodes_[i].z = nodes[i].z;
selected_nodes_[i] = nodes_.get(i);
}
elems_.resize(valid_elem_size_);
selected_elems_.resize(valid_elem_size_);
for (size_t i = 0; i < valid_elem_size_; i++)
{
elems_[i].id = i;
elems_[i].type = oe_type;
elems_[i].vert_ptrs.resize(vnum);
for (size_t v = 0; v < vnum; v++)
{
elems_[i].vert_ptrs[v] = nodes_.get(elems[i].vert[v]->id);
}
selected_elems_[i] = elems_.get(i);
}
// 所有单元体都属于同一个组
valid_group_size_ = 1;
groups_.resize(1);
groups_[0].enabled = true;
groups_[0].type = oe_type;
groups_[0].phys_group = 0; // 默认组别为0
groups_[0].geom_group = 0; // 默认组别为0
groups_[0].part_group = 3;
for (size_t i = 0; i < elems_.size(); i++)
{
groups_[0].elem_ptrs.push_back(elems_.get(i));
}
groups_[0].enable_elements();
initialized_ = true;
selected_groups_.resize(1);
selected_groups_[0] = &groups_[0];
return;
}
template <typename T>
void gctl::mesh_io::import_from(const array<T> &elems, const array<vertex2dc> &nodes, int x_id, int y_id)
{
reset(); // 重置网格数据
const std::type_info &tinfo = typeid(T);
element_type_enum oe_type = match_type(tinfo);
int vnum = elem_size(oe_type);
valid_node_size_ = nodes.size();
valid_elem_size_ = elems.size();
int xyz_ref[3];
nodes_.resize(valid_node_size_);
selected_nodes_.resize(valid_node_size_);
for (size_t i = 0; i < valid_node_size_; i++)
{
nodes_[i].id = i;
xyz_ref[0] = 0.0;
xyz_ref[1] = 0.0;
xyz_ref[2] = 0.0;
xyz_ref[x_id] = nodes[i].x;
xyz_ref[y_id] = nodes[i].y;
nodes_[i].x = xyz_ref[0];
nodes_[i].y = xyz_ref[1];
nodes_[i].z = xyz_ref[2];
selected_nodes_[i] = nodes_.get(i);
}
elems_.resize(valid_elem_size_);
selected_elems_.resize(valid_elem_size_);
for (size_t i = 0; i < valid_elem_size_; i++)
{
elems_[i].id = i;
elems_[i].type = oe_type;
elems_[i].vert_ptrs.resize(vnum);
for (size_t v = 0; v < vnum; v++)
{
elems_[i].vert_ptrs[v] = nodes_.get(elems[i].vert[v]->id);
}
selected_elems_[i] = elems_.get(i);
}
// 所有单元体都属于同一个组
valid_group_size_ = 1;
groups_.resize(1);
groups_[0].enabled = true;
groups_[0].type = oe_type;
groups_[0].phys_group = 0; // 默认组别为0
groups_[0].geom_group = 0; // 默认组别为0
groups_[0].part_group = 3;
for (size_t i = 0; i < elems_.size(); i++)
{
groups_[0].elem_ptrs.push_back(elems_.get(i));
}
groups_[0].enable_elements();
initialized_ = true;
selected_groups_.resize(1);
selected_groups_[0] = &groups_[0];
return;
}
};
#endif // _GCTL_MESH_IO_H