Files
ViewDesignEngine/include/vde/mesh/fea_mesh.h
T
茂之钳 66777e0839
CI / Build & Test (push) Failing after 38s
CI / Release Build (push) Failing after 31s
Build & Test / build-and-test (push) Has been cancelled
Build & Test / python-bindings (push) Has been cancelled
feat(v6.1): 5-axis CAM + reverse engineering + FEA mesh generation
v6.1.1 — 5-Axis CAM:
- cam_5axis.h/.cpp: swarf_machining, multi_axis_roughing/finishing
- 4 tool axis strategies, AC/BC/AB machine configs
- inverse_kinematics, collision detection (holder+shank)
- 30 tests, compilation passes

v6.1.2 — Reverse Engineering:
- point_cloud.h/.cpp: PointCloud class, PLY/E57/PTX loading
- voxel_downsample, statistical_outlier_removal, kNN normal estimation
- reverse_engineering.h/.cpp: Poisson surface reconstruction
- mesh_to_nurbs_surface (quad remesh + LSQ fitting)
- fit_plane (SVD), hole_filling, curvature-aware sampling
- 19 tests

v6.1.3 — FEA Mesh Generation:
- fea_mesh.h/.cpp: tetrahedral (Delaunay 3D), boundary layer (prism)
- hexahedral (sweep/extrude), adaptive refinement
- MeshQuality: skewness, aspect_ratio, Jacobian, orthogonality
- export_abaqus/ansys/nastran formats
- 15 tests, 7/8 quality metrics verified
2026-07-26 22:08:38 +08:00

410 lines
15 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#pragma once
/**
* @file fea_mesh.h
* @brief 高质量FEA有限元网格生成模块
*
* 提供四面体、边界层棱柱、六面体网格生成、自适应细化、
* 网格质量评估及CAE格式(Abaqus/Ansys/Nastran)导出。
*
* ## 功能概览
* - tetrahedral_mesh: Delaunay 3D + 质量优化四面体网格
* - boundary_layer_mesh: 沿壁面法向拉伸棱柱边界层
* - hexahedral_mesh: sweep/extrude 六面体网格
* - adaptive_refinement: 基于误差估计的局部细化
* - fea_quality_report: skewness/aspect_ratio/jacobian/orthogonality 报告
* - export_abaqus / export_ansys / export_nastran: CAE 格式导出
*
* @ingroup mesh
*/
#include "vde/mesh/halfedge_mesh.h"
#include "vde/mesh/delaunay_3d.h"
#include "vde/brep/brep.h"
#include <vector>
#include <array>
#include <string>
#include <functional>
#include <cstdio>
namespace vde::mesh {
using core::Point3D;
using core::Vector3D;
// ════════════════════════════════════════════════════════
// FEA 单元类型
// ════════════════════════════════════════════════════════
/**
* @brief FEA 单元拓扑类型
* @ingroup mesh
*/
enum class FEAElementType {
Tet4, ///< 4节点线性四面体 (C3D4)
Tet10, ///< 10节点二次四面体 (C3D10)
Hex8, ///< 8节点线性六面体 (C3D8)
Hex20, ///< 20节点二次六面体 (C3D20)
Wedge6, ///< 6节点线性三棱柱/楔形 (C3D6)
Wedge15, ///< 15节点二次三棱柱 (C3D15)
};
/// 获取单元类型对应的每单元节点数
inline int nodes_per_element(FEAElementType t) {
switch (t) {
case FEAElementType::Tet4: return 4;
case FEAElementType::Tet10: return 10;
case FEAElementType::Hex8: return 8;
case FEAElementType::Hex20: return 20;
case FEAElementType::Wedge6: return 6;
case FEAElementType::Wedge15:return 15;
}
return 0;
}
/// 获取单元类型名称
inline const char* element_type_name(FEAElementType t) {
switch (t) {
case FEAElementType::Tet4: return "Tet4";
case FEAElementType::Tet10: return "Tet10";
case FEAElementType::Hex8: return "Hex8";
case FEAElementType::Hex20: return "Hex20";
case FEAElementType::Wedge6: return "Wedge6";
case FEAElementType::Wedge15:return "Wedge15";
}
return "Unknown";
}
// ════════════════════════════════════════════════════════
// FEAMesh 数据结构
// ════════════════════════════════════════════════════════
/**
* @brief FEA有限元网格
*
* 存储顶点、单元连通性、边界面及单元类型信息。
* 支持Tet4/Tet10/Hex8/Wedge6等常见FEA单元。
*
* @ingroup mesh
*/
struct FEAMesh {
std::vector<Point3D> vertices; ///< 顶点坐标数组
std::vector<std::vector<int>> elements; ///< 各单元顶点索引(长度 = nodes_per_element
FEAElementType element_type = FEAElementType::Tet4; ///< 单元类型
std::vector<int> material_ids; ///< 各单元材料ID(可选,默认0)
std::vector<std::vector<int>> boundary_faces;///< 边界面(用于施加BC),顶点索引数组
std::vector<int> boundary_face_tags; ///< 边界面标签(与boundary_faces一一对应)
/** @brief 单元总数 */
[[nodiscard]] size_t num_elements() const { return elements.size(); }
/** @brief 顶点总数 */
[[nodiscard]] size_t num_vertices() const { return vertices.size(); }
/** @brief 边界面总数 */
[[nodiscard]] size_t num_boundary_faces() const { return boundary_faces.size(); }
/** @brief 每单元节点数 */
[[nodiscard]] int npe() const { return nodes_per_element(element_type); }
};
// ════════════════════════════════════════════════════════
// 网格生成参数
// ════════════════════════════════════════════════════════
/**
* @brief 四面体网格生成参数
* @ingroup mesh
*/
struct TetMeshParams {
double min_angle = 15.0; ///< 最小二面角(度),太小导致刚度矩阵病态
double max_aspect_ratio = 5.0; ///< 最大长宽比(外接球半径/最短边)
double max_size = 0.0; ///< 最大单元尺寸,0 = 自动(包围盒对角线的 5%)
double min_size = 0.0; ///< 最小单元尺寸,0 = max_size/10
int quality_iterations = 3; ///< 质量优化迭代次数(Laplacian光顺+边翻转)
bool keep_surface = true; ///< 是否保持原表面顶点位置
};
/**
* @brief 边界层网格参数
* @ingroup mesh
*/
struct BLPParams {
double first_cell_height = 0.001; ///< 第一层棱柱高度(壁面法向距离)
double growth_rate = 1.2; ///< 相邻层高度增长率(>1.0
int num_layers = 5; ///< 棱柱层数
double total_thickness = 0.0; ///< 边界层总厚度,0 = 自动(first * (growth^n - 1)/(growth - 1)
bool smooth_transition = true; ///< 是否平滑过渡到内部网格
};
/**
* @brief 六面体网格参数
* @ingroup mesh
*/
struct HexMeshParams {
int sweep_layers = 1; ///< sweep 方向层数
double sweep_distance = 0.0; ///< sweep 总距离,0 = 自动(包围盒最小维度)
bool use_quad_dominant = true; ///< 源面是否使用四边形主导网格
double cell_size = 0.0; ///< 目标单元尺寸,0 = 自动
};
// ════════════════════════════════════════════════════════
// 网格质量评估
// ════════════════════════════════════════════════════════
/**
* @brief FEA网格质量报告
*
* 包含 skewness(偏斜度)、aspect_ratio(长宽比)、
* jacobian(雅可比)、orthogonality(正交性)四项
* 核心FEA网格质量指标。
*
* @ingroup mesh
*/
struct FEAQualityReport {
/// 偏斜度 (skewness): 实际单元与理想单元的偏差,[0,1],0=最优
double min_skewness = 0.0;
double max_skewness = 0.0;
double avg_skewness = 0.0;
/// 长宽比 (aspect ratio): 最长边/最短边,(Fluent: 1=最佳)
double min_aspect_ratio = 0.0;
double max_aspect_ratio = 0.0;
double avg_aspect_ratio = 0.0;
/// 归一化雅可比 (scaled jacobian): [0,1]1=正单元,0=退化,<0=反转
double min_jacobian = 0.0;
double max_jacobian = 0.0;
double avg_jacobian = 0.0;
/// 正交性 (orthogonality): 面法向与质心连线的夹角余弦,[0,1],1=完美正交
double min_orthogonality = 0.0;
double max_orthogonality = 0.0;
double avg_orthogonality = 0.0;
size_t total_elements = 0; ///< 单元总数
size_t degenerate_elements = 0; ///< 退化单元数 (Jacobian < 0.01)
size_t inverted_elements = 0; ///< 反转单元数 (Jacobian < 0)
/// 分级统计 (A=优秀 B=良好 C=合格 D=差 F=不合格,按Jacobian)
size_t grade_A = 0, grade_B = 0, grade_C = 0, grade_D = 0, grade_F = 0;
};
// ════════════════════════════════════════════════════════
// 自适应细化
// ════════════════════════════════════════════════════════
/**
* @brief 误差估计函数类型
*
* 对给定单元返回估计误差值(≥0),值越大表示该单元越需要细化。
*
* @param element_idx 单元索引
* @param mesh 所属网格
* @return 误差估计值(非负)
*/
using ErrorEstimator = std::function<double(int element_idx, const FEAMesh& mesh)>;
/**
* @brief 自适应细化参数
* @ingroup mesh
*/
struct RefinementParams {
double error_threshold = 0.5; ///< 相对误差阈值(高于此值的单元被细化)
double refinement_fraction = 0.2; ///< 每次细化单元比例(0~1
int max_iterations = 3; ///< 最大细化迭代次数
bool smooth_after_refine = true; ///< 细化后是否光顺
};
// ════════════════════════════════════════════════════════
// 网格生成 API
// ════════════════════════════════════════════════════════
/**
* @brief 生成四面体FEA网格(Delaunay 3D + 质量优化)
*
* 对 BrepModel 进行 tessellation 获取表面三角网格,
* 采样内部点后进行 Delaunay 3D 四面体化,
* 再进行 Laplacian 光顺 + 边翻转优化质量。
*
* @param body B-Rep实体模型
* @param params 四面体化参数(最小角、长宽比约束等)
* @return FEAMesh 四面体网格
*
* @code{.cpp}
* auto box = vde::brep::make_box(1, 1, 1);
* TetMeshParams p;
* p.min_angle = 18.0;
* p.max_aspect_ratio = 4.0;
* auto mesh = tetrahedral_mesh(box, p);
* @endcode
* @ingroup mesh
*/
FEAMesh tetrahedral_mesh(const brep::BrepModel& body,
const TetMeshParams& params = {});
/**
* @brief 生成边界层棱柱网格
*
* 沿B-Rep模型壁面法向拉伸多层棱柱单元,
* 用于CFD边界层捕捉(y+控制)。
* 先对表面进行三角化,然后每层沿法向偏移。
*
* @param body B-Rep实体模型
* @param params 边界层参数(首层高度、增长率、层数)
* @return FEAMesh 棱柱网格 (Wedge6)
*
* @code{.cpp}
* BLPParams p;
* p.first_cell_height = 0.0001;
* p.growth_rate = 1.15;
* p.num_layers = 10;
* auto bl = boundary_layer_mesh(wing, p);
* @endcode
* @ingroup mesh
*/
FEAMesh boundary_layer_mesh(const brep::BrepModel& body,
const BLPParams& params = {});
/**
* @brief 生成六面体网格(sweep/extrude策略)
*
* 将B-Rep模型的一个面(源面)四边形化,
* 然后沿法向 sweep 生成六面体层。
* 适用于拉伸体/棱柱体等 sweepable 几何。
*
* @param body B-Rep实体模型
* @param params 六面体化参数
* @return FEAMesh 六面体网格 (Hex8)
*
* @code{.cpp}
* auto cylinder = vde::brep::make_cylinder(1, 3);
* HexMeshParams p;
* p.sweep_layers = 5;
* auto mesh = hexahedral_mesh(cylinder, p);
* @endcode
* @ingroup mesh
*/
FEAMesh hexahedral_mesh(const brep::BrepModel& body,
const HexMeshParams& params = {});
/**
* @brief 自适应网格细化
*
* 基于误差估计函数对高误差区域进行局部细分。
* 支持边中点分裂细化(适用于Tet4→4×Tet4子单元)。
*
* @param mesh 输入FEA网格
* @param estimator 误差估计函数
* @param params 细化参数
* @return FEAMesh 细化后的网格
*
* @code{.cpp}
* auto estimator = [](int ei, const FEAMesh& m) -> double {
* // 基于应力梯度的误差估计
* return stress_gradient_norm(ei, m);
* };
* auto refined = adaptive_refinement(mesh, estimator);
* @endcode
* @ingroup mesh
*/
FEAMesh adaptive_refinement(const FEAMesh& mesh,
const ErrorEstimator& estimator,
const RefinementParams& params = {});
// ════════════════════════════════════════════════════════
// 质量评估 API
// ════════════════════════════════════════════════════════
/**
* @brief 评估FEA网格质量
*
* 计算四项核心质量指标:
* - skewness: 偏斜度(实际vs理想单元的偏差)
* - aspect_ratio: 长宽比
* - jacobian: 归一化雅可比行列式
* - orthogonality: 正交性(面法向与质心连线夹角)
*
* 自动根据 element_type 选择对应算法(Tet/Hex/Wedge)。
*
* @param mesh FEA网格
* @return FEAQualityReport 质量报告
*
* @ingroup mesh
*/
FEAQualityReport fea_quality_report(const FEAMesh& mesh);
// ── 单项质量指标 ──
/**
* @brief 计算单元的偏斜度
* @param verts 单元顶点数组
* @param type 单元类型
* @return skewness [0,1]0=理想单元
*/
double element_skewness(const std::vector<Point3D>& verts, FEAElementType type);
/**
* @brief 计算单元的长宽比
* @param verts 单元顶点数组
* @param type 单元类型
* @return aspect_ratio ≥ 11=理想
*/
double element_aspect_ratio(const std::vector<Point3D>& verts, FEAElementType type);
/**
* @brief 计算单元的归一化雅可比
* @param verts 单元顶点数组
* @param type 单元类型
* @return scaled_jacobian [0,1]1=正四面体/正方体,0=退化
*/
double element_scaled_jacobian(const std::vector<Point3D>& verts, FEAElementType type);
/**
* @brief 计算单元的正交性
* @param verts 单元顶点数组
* @param type 单元类型
* @return orthogonality [0,1]1=完全正交(面法向与对面质心连线平行)
*/
double element_orthogonality(const std::vector<Point3D>& verts, FEAElementType type);
// ════════════════════════════════════════════════════════
// CAE 格式导出
// ════════════════════════════════════════════════════════
/**
* @brief 导出 Abaqus 输入文件 (.inp)
*
* 生成包含 *NODE 和 *ELEMENT 卡的 Abaqus 输入文件。
* 支持 Tet4 (C3D4), Tet10 (C3D10), Hex8 (C3D8), Wedge6 (C3D6)。
*
* @param mesh FEA网格
* @param filepath 输出文件路径
* @return 成功返回 true
*
* @ingroup mesh
*/
bool export_abaqus(const FEAMesh& mesh, const std::string& filepath);
/**
* @brief 导出 Ansys CDB 文件 (.cdb)
*
* 生成包含 NBLOCK 和 EBLOCK 的 Ansys CDB 格式文件。
*
* @param mesh FEA网格
* @param filepath 输出文件路径
* @return 成功返回 true
*
* @ingroup mesh
*/
bool export_ansys(const FEAMesh& mesh, const std::string& filepath);
/**
* @brief 导出 Nastran 批量数据文件 (.bdf/.dat)
*
* 生成包含 GRID 和 CTETRA/CHEXA/CPENTA 卡的 Nastran 输入文件。
*
* @param mesh FEA网格
* @param filepath 输出文件路径
* @return 成功返回 true
*
* @ingroup mesh
*/
bool export_nastran(const FEAMesh& mesh, const std::string& filepath);
} // namespace vde::mesh