第14章 各向异性网格(Anisotropic Mesh):方向感知的网格生成
14.1 学习目标
- 理解各向同性网格(Isotropic Mesh)与各向异性网格(Anisotropic Mesh)的本质区别:标量尺寸 vs 张量度量(metric tensor)
- 掌握通过
merge()加载.pos文件作为各向异性背景网格的方法,理解TT(张量三角形)格式中度量张量的含义 - 学会使用 bamg(Bidimensional Anisotropic Mesh Generator)作为二维各向异性网格生成器,包括
Mesh.Algorithm=7、Mesh.SmoothRatio、Mesh.AnisoMax等关键选项 - 理解各向异性网格在 CAE 中的典型应用场景:CFD 边界层网格(壁面法向加密、流向稀疏)、激波捕捉、复合材料界面
- 建立本章与第7章(背景网格)、第8章(尺寸场)的知识联系——各向异性背景网格是标量背景网格的张量推广
14.2 核心概念说明
14.2.1 各向同性 vs 各向异性网格
在前面的章节中,我们通过点级 lc、标量背景网格(第7章)、尺寸场(第8章)控制的网格都是各向同性(Isotropic)的。这意味着在空间的任意一点,网格尺寸在所有方向上都相同——单元是"正三角形"(2D)或"正四面体"(3D),没有方向偏好。
各向异性(Anisotropic)网格则不同:在空间中的每一点,网格尺寸是一个方向相关的量。不同方向允许不同的网格边长。例如,在 CFD 壁面附近: - 垂直于壁面的方向需要极细的网格(捕捉边界层速度梯度) - 平行于壁面的方向可以用较粗的网格(流向变化缓慢)
这种方向依赖性无法用单一的标量值描述,而需要一个 2x2(二维)或 3x3(三维)对称正定的度量张量(Metric Tensor)。
| 网格类型 | 尺寸描述 | 单元形状 | 典型场景 |
|---|---|---|---|
| 各向同性(Isotropic) | 标量 h(x,y,z) |
正三角形/正四面体 | 通用结构分析、无方向偏好的均匀细化 |
| 各向异性(Anisotropic) | 度量张量 M(x,y,z) ∈ R^(dxd) |
拉伸三角形/四面体 | CFD 边界层、激波、复合材料 |
14.2.2 度量张量(Metric Tensor)的几何意义
在二维空间中,度量张量 M 是一个 2x2 对称正定矩阵。它可以谱分解为:
M = R^T * diag(1/h1^2, 1/h2^2) * R
其中:
- h1 和 h2 是两个正交主方向上的期望网格边长
- R 是旋转矩阵,描述主方向在空间中的朝向
- 当 h1 = h2 时,退化为各向同性情况;当 h1 << h2 时,实现强各向异性(在一个方向上极度加密)
Gmsh 内部使用该度量张量来计算任意两点之间的各向异性距离,并据此驱动网格生成器构造拉伸单元。
14.2.3 bamg:二维各向异性网格生成器
Gmsh 内置的默认二维网格生成器 Mesh.Algorithm=6(Frontal-Delaunay)主要面向各向同性网格。对于各向异性二维网格,Gmsh 调用 bamg(Bidimensional Anisotropic Mesh Generator),通过设置 Mesh.Algorithm=7 启用。bamg 是一个基于 Delaunay 的各向异性网格生成器,能够根据度量张量场生成高质量的各向异性三角形。
关键选项:
| 选项 | 含义 | 建议值 |
|---|---|---|
Mesh.Algorithm |
二维网格算法 | 7 = bamg |
Mesh.SmoothRatio |
平滑比,控制相邻单元尺寸变化的剧烈程度 | 1.2 ~ 3.0 |
Mesh.AnisoMax |
最大各向异性比(最长边/最短边) | 100 ~ 10000(视边界层需求) |
14.2.4 各向异性背景网格的 .pos 格式
与第7章使用的标量 .pos 格式(ST 标量三角形)不同,各向异性背景网格使用的是 TT(Tensor Triangle,张量三角形)格式:
View "nodalMetric" {
TT(x1,y1,z1, x2,y2,z2, x3,y3,z3){m11,m12,m13, m21,m22,m23, m31,m32,m33, ...};
};
- 前三个括号:三角形三个顶点的坐标(共9个值)
- 花括号内:每个顶点上的 3x3 度量张量(对称矩阵,共9个值),三个顶点共27个值
- 对于二维问题(z=0),度量张量的第3行/列退化为
(0, 0, 1),实际生效的是左上角 2x2 子矩阵
在 t17_bgmesh.pos 中,度量张量在方块的左半部分值较小(网格较粗),右上角区域值很大(网格较细),且张量表现出明显的方向性(非对角线元素非零),引导生成拉伸方向的三角形。
14.2.5 各向异性 mesh::field 定义方式
除了加载 .pos 文件作为背景网格外,Gmsh 也支持通过 gmsh::model::mesh::field API 程序化地定义各向异性尺寸场。使用 F(MathEval)场的矩阵表达式或通过 setNumber 设置矩阵参数的方式可构建自定义度量场,但通常 .pos 文件方式更为实用——它可以由外部求解器(如误差估计器)生成,并在 Gmsh 中直接用于网格重剖。
14.2.6 与第7章和第8章的关系
本章内容与第7章和第8章形成递进关系:
第7章: 标量背景网格(ST 格式)—— 每点一个标量尺寸 h
↓ 推广
第8章: 尺寸场(Distance/MathEval/Box 等)—— 参数化控制标量尺寸
↓ 推广
第14章: 各向异性背景网格(TT 格式)—— 每点一个度量张量 M(方向+尺寸)
三者共享 setAsBackgroundMesh() 的统一接口,差异仅在于数据本身是标量还是张量。当背景网格提供的是张量数据时,Gmsh 自动将其作为各向异性度量场处理。
14.3 C++ 代码逐段讲解
14.3.1 创建几何体
首先创建一个 4x4 的二维方块作为计算域:
#include <set>
#include <cmath>
#include <gmsh.h>
int main(int argc, char **argv)
{
gmsh::initialize();
gmsh::model::add("t14_anisotropic");
// 创建一个 4x4 的二维方块,左下角 (-2, -2),边长 4
gmsh::model::occ::addRectangle(-2, -2, 0, 4, 4);
gmsh::model::occ::synchronize();
解释:通过 OpenCASCADE 内核创建一个 [-2, 2] x [-2, 2] 的正方形平面区域。synchronize() 将 CAD 模型同步到 Gmsh 内部数据结构。该区域将作为各向异性网格的剖分域。
14.3.2 加载各向异性背景网格文件
// 加载包含各向异性度量张量的后处理视图
try {
gmsh::merge("../t17_bgmesh.pos");
} catch(...) {
gmsh::logger::write("无法加载各向异性背景网格文件: 退出!");
gmsh::finalize();
return 0;
}
解释:gmsh::merge() 加载外部后处理文件。这里加载的 t17_bgmesh.pos 文件包含一个名为 "nodalMetric" 的后处理视图,其中每个三角形的每个顶点都携带一个 3x3 度量张量。文件中的 TT 条目定义了张量场在空间中的分布:在域的不同位置度量张量的大小和方向各不相同,从而实现空间变化的方向性网格控制。
该文件通常由外部工具(如误差估计器、自适应求解器、或 Python 脚本)生成,覆盖整个计算域。对于实际 CAE 工作流,你可以用自己的求解器输出替换此文件。
14.3.3 将视图注册为背景网格
// 将加载的后处理视图注册为各向异性背景网格
int bgField = gmsh::model::mesh::field::add("PostView");
gmsh::model::mesh::field::setNumber(bgField, "ViewIndex", 0);
gmsh::model::mesh::field::setAsBackgroundMesh(bgField);
解释:这是将外部数据关联到网格生成管线的关键三步:
field::add("PostView")创建一个PostView类型的尺寸场。PostView场类型从已加载的后处理视图中读取尺寸信息。field::setNumber(bgField, "ViewIndex", 0)指定使用第 0 号视图(即merge()加载的第一个视图)。如果.pos文件包含多个视图,可通过改变此索引选择不同视图。field::setAsBackgroundMesh(bgField)将该场设为全局背景网格,所有后续网格生成操作都将查询此场中的度量张量。
PostView 场能自动区分标量视图(ST,生成各向同性网格)和张量视图(TT,生成各向异性网格),无需手动指定。
14.3.4 配置 bamg 各向异性网格生成器
// 配置 bamg 各向异性二维网格生成器
gmsh::option::setNumber("Mesh.SmoothRatio", 3);
gmsh::option::setNumber("Mesh.AnisoMax", 1000);
gmsh::option::setNumber("Mesh.Algorithm", 7);
解释:三个选项协同配置 bamg 的行为:
Mesh.Algorithm = 7:显式选择 bamg 作为二维网格生成器。Gmsh 的默认算法(Frontal-Delaunay, 算法 6)不能生成各向异性网格——如果不设此项,Gmsh 会从度量张量中提取各向同性尺寸(取主方向最大尺寸),仅生成各向同性网格。Mesh.SmoothRatio = 3:控制相邻单元之间的尺寸过渡平滑度。该值越大,网格尺寸变化越剧烈。bamg 需要对梯度合理的度量场才能收敛,若场中的尺寸变化过于剧烈,需调小此值。Mesh.AnisoMax = 1000:允许的最大各向异性比(最长边与最短边之比)。此处设 1000,允许在边界层区域产生极度拉伸的三角形。实际值应根据物理需求设定——CFD 边界层通常需要 100~10000 的比值。
注意:
Mesh.SmoothRatio对 bamg 的作用与对各向同性生成器不同。bamg 用它在度量空间中进行梯度限制(gradient limiting),防止度量张量在空间上变化过快导致网格质量恶化。
14.3.5 生成网格并输出
// 生成二维各向异性网格
gmsh::model::mesh::generate(2);
// 保存为 .msh 文件
gmsh::write("t14_anisotropic.msh");
// 启动 GUI 查看结果(如未指定 -nopopup)
std::set<std::string> args(argv, argv + argc);
if(!args.count("-nopopup")) gmsh::fltk::run();
gmsh::finalize();
return 0;
}
解释:mesh::generate(2) 生成二维网格,Gmsh 内部调用 bamg 的库函数,依据度量张量场在各处生成尺寸和方向匹配的三角形。生成后通过 gmsh::write() 导出为标准 .msh 格式文件,可直接用于后续 CAE 求解器。fltk::run() 打开 Gmsh 的图形界面,供用户可视化检查各向异性网格效果。
14.4 面向 CAE 的应用场景
14.4.1 CFD 边界层网格
在计算流体力学(CFD)中,壁面附近的边界层具有极强的速度梯度,需要在壁面法向布置极细的网格,而流向(平行于壁面)则可以粗糙得多。各向异性网格天然适合此场景:
- 度量张量的主轴在壁面法向上对应极小尺寸
h_n(如 0.001mm) - 壁面切向对应较大尺寸
h_t(如 1mm) - 各向异性比
h_t / h_n可达 1000 以上
传统方法通过结构化边界层网格(棱柱层)实现,而 bamg + 各向异性背景网格提供了非结构化替代方案,能更好地处理复杂几何。
14.4.2 激波捕捉
在高超声速流动中,激波是一个极薄的区域(几倍分子平均自由程),需要用极细的网格解析。激波的法向需要加密,而激波面内的方向可以粗糙。自适应求解器可在激波位置输出各向异性度量张量,迭代生成对齐激波方向的拉伸网格。
14.4.3 复合材料界面
复合材料(如纤维增强层合板)中,基体与纤维的界面处应力梯度在界面法向远大于切向。各向异性网格可以在不显著增加总单元数的前提下,在界面法向提高分辨率。
14.5 各向异性背景网格的生成方法
在实际 CAE 工作流中,各向异性背景网格通常不由手工编写,而是通过以下途径自动生成:
- 自适应误差估计:在粗网格上求解,计算每个单元的误差指示器(如 Hessian recovery),然后根据 Hessian 矩阵的特征值和特征向量构造各向异性度量张量,导出为
.pos文件 - 解析度量场:对于简单几何和已知解特征的问题,可通过 Python/MATLAB 脚本根据几何位置直接计算度量张量并写入
.pos - CFD 求解器内置输出:某些求解器(如 SU2、Code_Saturne)支持直接输出 Gmsh 格式的各向异性度量场
以下是一个简单的 Python 片段示意如何生成 .pos 文件中的各向异性数据:
# 示意: 生成壁面法向加密的各向异性度量张量 .pos 文件
# 实际使用时需要根据几何计算每个节点的位置和度量张量
import numpy as np
def metric_at(x, y):
"""在壁面 y=0 附近,法向(y)加密,切向(x)稀疏"""
dist = y # 到壁面距离
h_normal = 0.001 + 0.1 * dist # 壁面法向: 0.001 ~ 远场 0.1
h_tangential = 0.1 # 壁面切向: 恒为 0.1
# 度量张量 M = diag(1/h_x^2, 1/h_y^2)
return np.array([[1/h_tangential**2, 0],
[0, 1/h_normal**2]])
# 输出为 .pos TT 格式...
14.6 关键 API 速查表
| API | 用途 | 说明 |
|---|---|---|
gmsh::merge(filename) |
加载后处理视图文件 | 支持 .pos 格式,自动解析 ST/TT 等单元类型 |
gmsh::model::mesh::field::add("PostView") |
创建 PostView 尺寸场 | 将已加载视图的内容注册为可用的尺寸场 |
gmsh::model::mesh::field::setNumber(f, "ViewIndex", idx) |
选择视图索引 | 指定使用 merge 加载的第几个视图(从 0 开始) |
gmsh::model::mesh::field::setAsBackgroundMesh(f) |
设为背景网格 | 全局生效,所有后续 generate() 均受其控制 |
option::setNumber("Mesh.Algorithm", 7) |
选择 bamg 算法 | 二维各向异性网格的必要条件 |
option::setNumber("Mesh.SmoothRatio", v) |
度量梯度平滑比 | 控制 bamg 对度量张量空间变化的平滑程度 |
option::setNumber("Mesh.AnisoMax", v) |
最大各向异性比 | 允许的最大边长比,防止过度拉伸导致数值问题 |
gmsh::model::mesh::generate(2) |
生成二维网格 | 在 Mesh.Algorithm=7 时调用 bamg |
gmsh::write("file.msh") |
输出网格文件 | 标准 Gmsh 网格格式,包含节点、单元及度量数据 |
14.7 注意事项与常见问题
-
bamg 仅支持二维:
Mesh.Algorithm=7对三维网格无效。对于三维各向异性网格,需使用 Gmsh 与外部库(如 MMG3D)的集成,或分步骤生成(先生成二维边界层,再向三维拉伸)。 -
度量张量必须光滑:bamg 对度量张量的空间连续性有要求。若
.pos文件中相邻三角形的度量值差异过大,需增大Mesh.SmoothRatio或先在外部对度量场进行平滑处理。 -
文件中不能混用 ST 和 TT:作为各向异性背景网格的视图应全部使用
TT类型。如果使用ST,Gmsh 将退化为各向同性处理。 -
三维张量格式:即使做二维问题,
.pos文件中的度量张量仍然是 3x3 格式。对于 z=0 平面上的二维问题,第三行/列通常为(0, 0, 1)。 -
与其他尺寸约束的冲突:如第8章所述,Gmsh 多层尺寸优先级链的各层取最小值。如果几何点上有极小的
lc值,它会盖过背景网格的度量张量。如需纯粹依赖背景网格,应关闭Mesh.MeshSizeFromPoints等其他来源:
cpp
gmsh::option::setNumber("Mesh.MeshSizeFromPoints", 0);
gmsh::option::setNumber("Mesh.MeshSizeFromCurvature", 0);
gmsh::option::setNumber("Mesh.MeshSizeExtendFromBoundary", 0);
14.8 完整可运行代码
// -----------------------------------------------------------------------------
// Chapter 14: Anisotropic Mesh — Direction-Aware Mesh Generation
//
// 功能: 加载各向异性背景网格 (.pos),使用 bamg 在方块上生成各向异性二维网格
//
// 编译 (需链接 Gmsh SDK):
// g++ -o ch14_aniso ch14_aniso.cpp -lgmsh
//
// 运行:
// ./ch14_aniso (带 GUI 查看)
// ./ch14_aniso -nopopup (仅生成 .msh 文件)
// -----------------------------------------------------------------------------
#include <set>
#include <cmath>
#include <gmsh.h>
int main(int argc, char **argv)
{
gmsh::initialize();
gmsh::model::add("ch14_anisotropic");
// ---- 1. 创建几何体 ----
// 创建一个 4x4 的二维方块,左下角 (-2, -2)
gmsh::model::occ::addRectangle(-2, -2, 0, 4, 4);
gmsh::model::occ::synchronize();
// ---- 2. 加载各向异性背景网格 ----
// t17_bgmesh.pos 中包含 TT(张量三角形)数据,定义了度量张量场
try {
gmsh::merge("../t17_bgmesh.pos");
} catch(...) {
gmsh::logger::write("Could not load anisotropic background mesh; exiting.");
gmsh::finalize();
return 0;
}
// ---- 3. 将后处理视图注册为背景网格 ----
int bgField = gmsh::model::mesh::field::add("PostView");
gmsh::model::mesh::field::setNumber(bgField, "ViewIndex", 0);
gmsh::model::mesh::field::setAsBackgroundMesh(bgField);
// ---- 4. 配置 bamg 各向异性二维网格生成器 ----
gmsh::option::setNumber("Mesh.SmoothRatio", 3);
gmsh::option::setNumber("Mesh.AnisoMax", 1000);
gmsh::option::setNumber("Mesh.Algorithm", 7);
// ---- 5. 生成二维各向异性网格 ----
gmsh::model::mesh::generate(2);
// ---- 6. 输出网格 ----
gmsh::write("ch14_anisotropic.msh");
// ---- 7. 可选 GUI 查看 ----
std::set<std::string> args(argv, argv + argc);
if(!args.count("-nopopup")) gmsh::fltk::run();
gmsh::finalize();
return 0;
}
14.9 本章小结
- 各向异性网格通过度量张量(Metric Tensor)在每一点同时描述网格尺寸和方向偏好,突破各向同性网格"所有方向同尺寸"的限制。
.pos文件中的TT(张量三角形)格式携带每个顶点上的 3x3 度量张量,是各向异性背景网格的数据载体。PostView场类型 +setAsBackgroundMesh()将外部度量数据路由到 Gmsh 网格生成管线。Mesh.Algorithm=7启用 bamg 是生成二维各向异性网格的必要条件;Mesh.AnisoMax控制各向异性比的物理上限。- 本章内容与第7章和第8章构成完整递进:标量尺寸 -> 标量尺寸场 -> 张量度量场(各向异性)。
- 在 CAE 实践中,CFD 边界层、激波捕捉和复合材料界面是各向异性网格的三个核心应用场景。