第22章 遍历模型与网格数据:前处理查询 API 全解
22.1 学习目标
- 理解 Gmsh 模型实体(Model Entity)的
(dim, tag)标识体系,掌握getEntities()遍历全部几何实体 - 掌握
mesh::getNodes()按实体或全局获取节点坐标,理解交错(interleaved)坐标存储格式 - 掌握
mesh::getElements()获取单元类型、单元标签和节点连接列表(element connectivity),以及getElementsByType()按类型筛选 - 学会使用
getType()和getEntityName()查询实体类型与名称 - 掌握
getAdjacencies()查询上邻接(upward)和下邻接(downward)关系 - 理解物理组(Physical Group)与
getPhysicalGroupsForEntity()/getPhysicalName()的查询 - 掌握分区信息查询:
getPartitions()与getParent()追溯分区实体的原始父实体 - 掌握
mesh::getElementProperties()查询单元类型的名称、维度、阶次、节点数和参数坐标 - 能够编写完整的前处理数据提取程序,为有限元求解器输入准备网格数据
22.2 核心概念说明
22.2.1 模型实体(Model Entity)与 (dim, tag) 标识
Gmsh 中所有几何信息由模型实体(Model Entity)组成,按维度分为四类:
| 维度 | 实体类型 | 英文名称 | 说明 |
|---|---|---|---|
| 0 | 点 | Point | 几何点 |
| 1 | 曲线 | Curve | 几何边 |
| 2 | 曲面 | Surface | 几何面 |
| 3 | 体 | Volume | 几何体 |
每个实体由一个 (dim, tag) 对唯一标识,其中 dim 为维度(0-3),tag 为严格正整数的标签。模型实体可以来自内置 geo 内核、OpenCASCADE occ 内核,也可以是离散实体(Discrete Entity)——由网格本身定义,没有底层 CAD 几何。
网格数据(Nodes 和 Elements)被分类(classified)到相应的模型实体上。例如:一个面实体包含其内部的三角形/四边形单元以及内部节点,而边界节点和边界边上的单元则存储在其边界实体上。这种分类关系使得前处理程序可以按实体精准提取网格子集。
22.2.2 网格数据结构概览
模型(Model)
├── 实体列表 (dim, tag) pairs
│ ├── Point (0, n) ← 含点单元 + 孤立节点
│ ├── Curve (1, n) ← 含线单元 + 内部节点
│ ├── Surface (2, n) ← 含三角形/四边形 + 内部节点
│ └── Volume (3, n) ← 含四面体/六面体等 + 内部节点
│
├── 节点 (Nodes)
│ ├── nodeTag: 全局唯一正整数
│ ├── coords: x1,y1,z1, x2,y2,z2, ... (交错存储)
│ └── parametricCoords: 参数坐标(可选)
│
├── 单元 (Elements)
│ ├── elemType: Gmsh 单元类型编号 (1=2节点线, 2=3节点三角形, 4=4节点四面体, ...)
│ ├── elemTags: 每种类型的单元标签列表
│ └── nodeTags: 每种类型的节点连接列表 (CCW 或 Gmsh 规定顺序)
│
└── 物理组 (Physical Groups)
└── (dim, physicalTag) 引用一组模型实体
22.2.3 单元类型编号与命名规则
Gmsh 预定义了数百种单元类型。常用的包括:
| 类型编号 | 名称 | 说明 | 节点数 |
|---|---|---|---|
| 1 | Line 2 | 2 节点线单元 | 2 |
| 2 | Triangle 3 | 3 节点三角形 | 3 |
| 3 | Quadrangle 4 | 4 节点四边形 | 4 |
| 4 | Tetrahedron 4 | 4 节点四面体 | 4 |
| 5 | Hexahedron 8 | 8 节点六面体 | 8 |
| 6 | Prism 6 | 6 节点三棱柱 | 6 |
| 7 | Pyramid 5 | 5 节点金字塔 | 5 |
| 8 | Line 3 | 3 节点二阶线单元 | 3 |
| 9 | Triangle 6 | 6 节点二阶三角形 | 6 |
| 15 | Point 1 | 1 节点点单元 | 1 |
通过 getElementProperties() 可以查询任意类型编号对应的完整属性。
22.2.4 邻接关系(Adjacencies)
Gmsh 为每个实体维护拓扑邻接关系:
- 上邻接(Upward Adjacencies):当前实体是哪些更高维实体的边界。例如一个面(dim=2)的上邻接是包含该面的体(dim=3);一条线(dim=1)的上邻接是包含该线的面。
- 下邻接(Downward Adjacencies):当前实体的边界由哪些更低维实体构成。例如一个面的下邻接是其边界线和边界点;一个体的下邻接是其边界面。
22.2.5 分区实体与父子关系
当网格被分区(见第21章)后,Gmsh 创建分区实体(Partition Entity)。通过 getPartitions(dim, tag) 可获取分区索引列表,通过 getParent(dim, tag) 可追溯该分区实体的原始父实体(parentDim, parentTag)。非分区实体的这两个查询返回空结果。
22.2.6 物理组(Physical Group)
物理组是模型实体的命名集合,仍按 (dim, physicalTag) 标识。它用于在网格导出时标记边界条件区域(如 inlet、outlet、wall 等)。通过 getPhysicalGroupsForEntity() 可反查某个实体属于哪些物理组。
22.3 C++ 代码逐段讲解
22.3.1 初始化与模型准备
#include <gmsh.h>
#include <iostream>
#include <vector>
int main(int argc, char **argv)
{
gmsh::initialize();
// 支持从命令行加载已有MSH文件,或自动创建示例几何
if(argc > 1 && argv[1][0] != '-') {
gmsh::open(argv[1]);
} else {
// 创建一个简单的锥体作为示例几何体
gmsh::model::occ::addCone(1, 0, 0, 1, 0, 0, 0.5, 0.1);
gmsh::model::occ::synchronize();
gmsh::model::mesh::generate();
}
// 获取模型名称和维度
std::string modelName;
gmsh::model::getCurrent(modelName);
int modelDim = gmsh::model::getDimension();
std::cout << "Model: " << modelName << " (" << modelDim << "D)\n";
这段代码初始化 Gmsh,可选择从 MSH 文件读取已有网格(gmsh::open())或自动创建一个锥体并生成网格。getCurrent() 返回当前模型名称,getDimension() 返回模型最高维度。
22.3.2 遍历所有实体:getEntities()
// 获取模型中所有实体的 (dim, tag) 对
std::vector<std::pair<int, int>> entities;
gmsh::model::getEntities(entities);
std::cout << "Total entities: " << entities.size() << "\n\n";
// 也可按维度过滤
// gmsh::model::getEntities(entities, 2); // 仅获取面实体 (dim=2)
getEntities() 返回一个 vector<pair<int,int>>,每个元素是一个 (dim, tag) 对。可选第二个参数 dim 按维度过滤(-1 表示全部维度)。这是遍历模型几何结构的入口 API。
常见使用模式: 在前处理程序中,首先调用 getEntities() 获取全部实体列表,然后遍历每个实体提取其网格数据。
22.3.3 遍历节点:mesh::getNodes()
for(auto e : entities) {
int dim = e.first, tag = e.second;
// ---- 获取该实体上的网格节点 ----
std::vector<std::size_t> nodeTags;
std::vector<double> nodeCoords, parametricCoords;
gmsh::model::mesh::getNodes(nodeTags, nodeCoords,
parametricCoords, dim, tag);
std::cout << "Entity (" << dim << "," << tag << "): "
<< nodeTags.size() << " nodes\n";
// 坐标按 x1,y1,z1, x2,y2,z2, ... 交错存储
for(std::size_t i = 0; i < nodeTags.size(); i++) {
double x = nodeCoords[i * 3 + 0];
double y = nodeCoords[i * 3 + 1];
double z = nodeCoords[i * 3 + 2];
// 在此构建求解器节点数据结构
}
mesh::getNodes() 的完整签名:
void getNodes(vector<size_t> &nodeTags,
vector<double> &coord,
vector<double> ¶metricCoord,
int dim = -1, int tag = -1,
bool includeBoundary = false,
bool returnParametricCoord = true);
关键参数说明:
- dim / tag:指定实体,只获取该实体上的节点。两者都设为 -1 则获取全部网格节点。
- includeBoundary:设为 true 时也会包含该实体边界上的节点(默认 false,只返回内部节点)。
- coord:坐标数组,按 x0, y0, z0, x1, y1, z1, ... 顺序交错存储。数组长度为 nodeTags.size() * 3。
- parametricCoords:节点的参数坐标(用于高阶单元),可用 returnParametricCoord=false 跳过。
前处理要点: 通常需要按实体提取节点(指定 dim/tag),然后在求解器中将它们映射为局部编号。三维坐标用 coords[i*3 + 0/1/2] 模式索引。
22.3.4 遍历单元:mesh::getElements()
// ---- 获取该实体上的网格单元 ----
std::vector<int> elemTypes;
std::vector<std::vector<std::size_t>> elemTags, elemNodeTags;
gmsh::model::mesh::getElements(elemTypes, elemTags,
elemNodeTags, dim, tag);
int totalElems = 0;
for(auto &tags : elemTags) totalElems += tags.size();
std::cout << " Elements: " << totalElems << " ("
<< elemTypes.size() << " types)\n";
mesh::getElements() 的签名:
void getElements(vector<int> &elementTypes,
vector<vector<size_t>> &elementTags,
vector<vector<size_t>> &nodeTags,
int dim = -1, int tag = -1);
关键数据结构:
- elementTypes:[type1, type2, ...],该实体上出现的单元类型编号列表。
- elementTags:[[tagsForType1], [tagsForType2], ...],与 elementTypes 一一对应,每项是单元标签的向量。
- nodeTags:[[nodesForType1], [nodesForType2], ...],与 elementTypes 一一对应。对于第 k 种类型,nodeTags[k] 包含所有该类单元的节点编号按序拼接——即连接性数组(connectivity)。
遍历每个单元的具体实现:
// 遍历每种单元类型
for(std::size_t iType = 0; iType < elemTypes.size(); iType++) {
int eType = elemTypes[iType];
auto &eTags = elemTags[iType];
auto &nTags = elemNodeTags[iType];
// 查询该类型每个单元有几个节点
std::string eName;
int eDim, eOrder, numNodes, numPrimaryNodes;
std::vector<double> localCoords;
gmsh::model::mesh::getElementProperties(
eType, eName, eDim, eOrder, numNodes,
localCoords, numPrimaryNodes);
std::cout << " Type " << eType << " (" << eName
<< "), order=" << eOrder
<< ", nodes/elem=" << numNodes
<< ", count=" << eTags.size() << "\n";
// 遍历该类型的每个单元
for(std::size_t j = 0; j < eTags.size(); j++) {
std::size_t elemTag = eTags[j];
// 该单元的节点连接从 nTags 中提取
// nTags[j*numNodes] 到 nTags[j*numNodes + numNodes - 1]
}
}
前处理要点: nodeTags[iType] 是展平的一维数组,第 j 个单元的 numNodes 个节点起始于索引 j * numNodes。构建求解器单元结构时,先通过 getElementProperties() 获取 numNodes,再逐单元切片提取。
22.3.5 单元属性查询:mesh::getElementProperties()
// 演示每一个单元类型的详细属性
for(auto eType : elemTypes) {
std::string eName;
int eDim, eOrder, numNodes, numPrimaryNodes;
std::vector<double> localCoord;
gmsh::model::mesh::getElementProperties(
eType, eName, eDim, eOrder, numNodes,
localCoord, numPrimaryNodes);
std::cout << " [" << eType << "] " << eName
<< ": dim=" << eDim << ", order=" << eOrder
<< ", nodes=" << numNodes
<< ", primaryNodes=" << numPrimaryNodes
<< "\n";
}
输出参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
eName |
string | 单元名称,如 "Triangle 3"、"Tetrahedron 4" |
eDim |
int | 单元维度 |
eOrder |
int | 单元阶次(1=线性, 2=二次, ...) |
numNodes |
int | 单元总节点数 |
localCoord |
vector |
参数空间中的节点局部坐标,交错存储 |
numPrimaryNodes |
int | 主节点数(不含边中点和内部高阶节点) |
22.3.6 邻接关系查询:getAdjacencies()
// ---- 查询上邻接和下邻接 ----
std::vector<int> upward, downward;
gmsh::model::getAdjacencies(dim, tag, upward, downward);
if(!upward.empty()) {
std::cout << " Upward: ";
for(auto adjTag : upward)
std::cout << "(" << dim+1 << "," << adjTag << ") ";
std::cout << "\n";
}
if(!downward.empty()) {
std::cout << " Downward: ";
for(auto adjTag : downward)
std::cout << "(" << dim-1 << "," << adjTag << ") ";
std::cout << "\n";
}
upward 返回更高维邻接实体的 tag(维度为 dim+1),downward 返回更低维邻接实体的 tag(维度为 dim-1)。实际用法:需记录维度偏移,upward 中的 tag 需要配合 dim+1 才能构成完整 (dim, tag) 标识。
典型场景: 已知一个面实体,查 upward 得到它属于哪个体(用于材料属性传播);已知一个体实体,查 downward 得到它的边界面(用于边界条件施加)。
22.3.7 物理组查询
// ---- 该实体属于哪些物理组 ----
std::vector<int> physicalTags;
gmsh::model::getPhysicalGroupsForEntity(dim, tag, physicalTags);
if(!physicalTags.empty()) {
std::cout << " Physical groups: ";
for(auto pt : physicalTags) {
std::string physName;
gmsh::model::getPhysicalName(dim, pt, physName);
std::cout << "\"" << physName << "\" ("
<< dim << "," << pt << ") ";
}
std::cout << "\n";
}
getPhysicalGroupsForEntity() 返回该实体所属的物理组标签列表。然后通过 getPhysicalName() 获取物理组的可读名称(如 "inlet"、"wall")。这是 CAE 前处理中识别边界条件区域的常用方法。
22.3.8 分区信息与父实体
// ---- 是否分区实体?父实体是谁? ----
std::vector<int> partitions;
gmsh::model::getPartitions(dim, tag, partitions);
if(!partitions.empty()) {
std::cout << " Partitions: ";
for(auto p : partitions) std::cout << p << " ";
int parentDim, parentTag;
gmsh::model::getParent(dim, tag, parentDim, parentTag);
std::cout << " <- parent (" << parentDim << ","
<< parentTag << ")\n";
}
分区后,getPartitions() 返回该实体所属分区的索引(从 0 起)。getParent() 追溯该分区实体来自哪个原始父实体。非分区实体两个查询均返回空结果。
22.3.9 实体类型与名称
// ---- 实体类型和名称 ----
std::string entityType;
gmsh::model::getType(dim, tag, entityType);
std::string entityName;
gmsh::model::getEntityName(dim, tag, entityName);
std::cout << "Entity " << entityName
<< " of type " << entityType
<< " (" << dim << "," << tag << ")\n";
getType() 返回实体类型字符串:
- dim=0: "Point"
- dim=1: "Curve"
- dim=2: "Surface"
- dim=3: "Volume"
- 离散实体: "Discrete Point", "Discrete Curve", "Discrete Surface", "Discrete Volume"
getEntityName() 返回在 GEO 脚本中或 OCC 建模时赋予的实体名称(可能为空)。
22.3.10 按类型获取单元:getElementsByType()(补充)
除 getElements() 一次性获取某实体上所有类型单元外,Gmsh 还提供按类型获取的 API:
// 获取2D三角单元(type=2)的所有单元
std::vector<std::size_t> triTags, triNodes;
gmsh::model::mesh::getElementsByType(2, triTags, triNodes);
std::cout << "Triangle 3 count: " << triTags.size() << "\n";
// triNodes 展平存储: [n0,n1,n2, n0,n1,n2, ...]
getElementsByType() 的签名:
void getElementsByType(int elementType,
vector<size_t> &elementTags,
vector<size_t> &nodeTags,
int tag = -1,
size_t task = 0,
size_t numTasks = 1);
参数 task 和 numTasks 支持并行分区读取:numTasks=N 时将数据分成 N 份,task=k 读取第 k 份。单线程使用时保持默认值 task=0, numTasks=1。
22.3.11 全局节点获取与求解器数据导出
当不关心实体划分,需要一次性导出全部网格时,可调用全局模式:
// 全局获取所有节点(dim=-1, tag=-1)
std::vector<std::size_t> allNodeTags;
std::vector<double> allCoords, allParamCoords;
gmsh::model::mesh::getNodes(allNodeTags, allCoords,
allParamCoords, -1, -1);
// 全局获取所有单元类型
std::vector<int> allElemTypes;
gmsh::model::mesh::getElementTypes(allElemTypes);
std::cout << "Global: " << allNodeTags.size() << " nodes, "
<< allElemTypes.size() << " element types\n";
getElementTypes() 可选 dim 和 tag 参数按实体过滤。全局模式下,这是导出完整求解器输入的最快方式。
22.3.12 完整遍历循环骨架
将所有查询整合到外层循环中,形成标准的前处理查询骨架:
std::vector<std::pair<int, int>> entities;
gmsh::model::getEntities(entities);
for(auto &e : entities) {
int dim = e.first, tag = e.second;
// 1. 基础信息
std::string eType, eName;
gmsh::model::getType(dim, tag, eType);
gmsh::model::getEntityName(dim, tag, eName);
// 2. 物理组
std::vector<int> physTags;
gmsh::model::getPhysicalGroupsForEntity(dim, tag, physTags);
// 3. 邻接关系
std::vector<int> up, down;
gmsh::model::getAdjacencies(dim, tag, up, down);
// 4. 分区信息
std::vector<int> parts;
gmsh::model::getPartitions(dim, tag, parts);
// 5. 节点
std::vector<std::size_t> nodeTags;
std::vector<double> coords, paramCoord;
gmsh::model::mesh::getNodes(nodeTags, coords, paramCoord, dim, tag);
// 6. 单元
std::vector<int> elemTypes;
std::vector<std::vector<std::size_t>> elemTags, elemNodeTags;
gmsh::model::mesh::getElements(elemTypes, elemTags, elemNodeTags,
dim, tag);
// 7. 按求解器需求重组数据...
}
22.3.13 清理与结束
gmsh::clear();
gmsh::finalize();
return 0;
}
gmsh::clear() 清除所有模型数据,gmsh::finalize() 释放 Gmsh 内部资源。注意如果之前使用了 gmsh::fltk::run() 启动 GUI,应在关闭窗口后再调用 clear()。
22.4 完整可运行代码
// ch22_full.cpp — 遍历模型所有实体并打印完整网格信息
#include <gmsh.h>
#include <iostream>
#include <vector>
#include <set>
int main(int argc, char **argv)
{
gmsh::initialize();
// 步骤1:准备模型(加载文件或创建示例几何)
if(argc > 1 && argv[1][0] != '-') {
gmsh::open(argv[1]);
} else {
// 创建一个复杂一点的几何:圆柱体方便展示所有实体类型
gmsh::model::occ::addCylinder(0, 0, 0, 0, 0, 1, 0.5);
gmsh::model::occ::synchronize();
// 设置网格尺寸并生成
gmsh::option::setNumber("Mesh.MeshSizeMin", 0.2);
gmsh::model::mesh::generate(3);
}
// 步骤2:打印模型基本信息
std::string modelName;
gmsh::model::getCurrent(modelName);
std::cout << "============================================\n";
std::cout << "Model: " << modelName
<< " (dim=" << gmsh::model::getDimension() << ")\n";
std::cout << "============================================\n\n";
// 步骤3:获取全部实体列表
std::vector<std::pair<int, int>> entities;
gmsh::model::getEntities(entities);
std::cout << "Total entities: " << entities.size() << "\n\n";
// 全局统计
std::size_t totalNodes = 0, totalElements = 0;
// 步骤4:遍历每个实体
for(auto &e : entities) {
int dim = e.first, tag = e.second;
// --- 4a. 实体类型与名称 ---
std::string entityType, entityName;
gmsh::model::getType(dim, tag, entityType);
gmsh::model::getEntityName(dim, tag, entityName);
std::cout << "---- Entity (" << dim << "," << tag << ") ----\n";
if(!entityName.empty())
std::cout << " Name: \"" << entityName << "\"\n";
std::cout << " Type: " << entityType << "\n";
// --- 4b. 节点 ---
std::vector<std::size_t> nodeTags;
std::vector<double> coords, paramCoord;
gmsh::model::mesh::getNodes(nodeTags, coords, paramCoord, dim, tag);
std::cout << " Nodes: " << nodeTags.size() << "\n";
totalNodes += nodeTags.size();
if(!nodeTags.empty()) {
// 打印前3个节点坐标示例
int showN = std::min(3, (int)nodeTags.size());
std::cout << " Sample coords: ";
for(int i = 0; i < showN; i++) {
std::cout << "n" << nodeTags[i] << "("
<< coords[i*3+0] << ","
<< coords[i*3+1] << ","
<< coords[i*3+2] << ") ";
}
std::cout << "\n";
}
// --- 4c. 单元 ---
std::vector<int> elemTypes;
std::vector<std::vector<std::size_t>> elemTags, elemNodeTags;
gmsh::model::mesh::getElements(elemTypes, elemTags, elemNodeTags,
dim, tag);
int entityElemCount = 0;
for(auto &tags : elemTags) entityElemCount += tags.size();
totalElements += entityElemCount;
std::cout << " Elements: " << entityElemCount << "\n";
// 打印每种单元类型的详细信息
for(std::size_t t = 0; t < elemTypes.size(); t++) {
std::string eName;
int eDim, eOrder, numNodes, numPrimaryNodes;
std::vector<double> localCoords;
gmsh::model::mesh::getElementProperties(
elemTypes[t], eName, eDim, eOrder, numNodes,
localCoords, numPrimaryNodes);
std::cout << " [" << elemTypes[t] << "] " << eName
<< ": " << elemTags[t].size()
<< " elems, order=" << eOrder
<< ", nodes/elem=" << numNodes;
// 展示第一个单元的连接性
if(!elemTags[t].empty()) {
std::cout << "\n elem#" << elemTags[t][0]
<< " nodes=[";
for(int n = 0; n < numNodes; n++) {
std::cout << elemNodeTags[t][n] << " ";
}
std::cout << "]";
}
std::cout << "\n";
}
// --- 4d. 邻接关系 ---
std::vector<int> up, down;
gmsh::model::getAdjacencies(dim, tag, up, down);
if(!up.empty()) {
std::cout << " Upward (" << dim+1 << "D): ";
for(auto u : up) std::cout << u << " ";
std::cout << "\n";
}
if(!down.empty()) {
std::cout << " Downward (" << dim-1 << "D): ";
for(auto d : down) std::cout << d << " ";
std::cout << "\n";
}
// --- 4e. 物理组 ---
std::vector<int> physTags;
gmsh::model::getPhysicalGroupsForEntity(dim, tag, physTags);
if(!physTags.empty()) {
std::cout << " Physical groups: ";
for(auto pt : physTags) {
std::string pn;
gmsh::model::getPhysicalName(dim, pt, pn);
std::cout << "\"" << pn << "\"(" << dim << "," << pt << ") ";
}
std::cout << "\n";
}
// --- 4f. 分区信息 ---
std::vector<int> parts;
gmsh::model::getPartitions(dim, tag, parts);
if(!parts.empty()) {
std::cout << " Partitions: ";
for(auto p : parts) std::cout << p << " ";
int pDim, pTag;
gmsh::model::getParent(dim, tag, pDim, pTag);
std::cout << "-> parent(" << pDim << "," << pTag << ")\n";
}
std::cout << "\n";
}
// 步骤5:输出全局统计
std::cout << "============================================\n";
std::cout << "Summary:\n";
std::cout << " Total entities: " << entities.size() << "\n";
std::cout << " Total nodes: " << totalNodes << "\n";
std::cout << " Total elements: " << totalElements << "\n";
// 全局单元类型统计
std::vector<int> allElemTypes;
gmsh::model::mesh::getElementTypes(allElemTypes);
std::cout << " Element types used: " << allElemTypes.size() << " (";
for(auto t : allElemTypes) std::cout << t << " ";
std::cout << ")\n";
std::cout << "============================================\n";
// 步骤6:可选GUI显示
std::set<std::string> args(argv, argv + argc);
if(!args.count("-nopopup")) gmsh::fltk::run();
gmsh::clear();
gmsh::finalize();
return 0;
}
编译与运行:
g++ -o ch22_full ch22_full.cpp -lgmsh
./ch22_full # 使用自动创建的圆柱体
./ch22_full input.msh # 加载已有的MSH网格文件
./ch22_full input.msh -nopopup # 不弹GUI,批处理模式
22.5 关键 API 速查表
22.5.1 模型查询
| API | 签名 | 说明 |
|---|---|---|
model::getEntities |
(vectorpair &dimTags, int dim=-1) |
获取全部或指定维度实体 (dim,tag) 列表 |
model::getCurrent |
(string &name) |
获取当前模型名称 |
model::getDimension |
() -> int |
获取模型最高维度(0-3) |
model::getType |
(int dim, int tag, string &type) |
获取实体类型字符串 |
model::getEntityName |
(int dim, int tag, string &name) |
获取实体名称(可为空) |
22.5.2 网格查询
| API | 签名 | 说明 |
|---|---|---|
mesh::getNodes |
(vec<size_t> &nodeTags, vec<double> &coord, vec<double> ¶mCoord, int dim=-1, int tag=-1, bool includeBoundary=false, bool returnParamCoord=true) |
获取节点标签和坐标(交错存储) |
mesh::getElements |
(vec<int> &elemTypes, vec<vec<size_t>> &elemTags, vec<vec<size_t>> &nodeTags, int dim=-1, int tag=-1) |
按实体获取所有单元类型、标签和连接性 |
mesh::getElementTypes |
(vec<int> &elemTypes, int dim=-1, int tag=-1) |
获取某实体上的单元类型列表(不含数据和标签) |
mesh::getElementsByType |
(int elemType, vec<size_t> &elemTags, vec<size_t> &nodeTags, int tag=-1, size_t task=0, size_t numTasks=1) |
按类型获取单元标签和展平连接性 |
mesh::getElementProperties |
(int elemType, string &name, int &dim, int &order, int &numNodes, vec<double> &localCoord, int &numPrimaryNodes) |
查询单元类型属性 |
22.5.3 拓扑与分组查询
| API | 签名 | 说明 |
|---|---|---|
model::getAdjacencies |
(int dim, int tag, vec<int> &upward, vec<int> &downward) |
获取上下邻接实体 tag 列表 |
model::getPhysicalGroupsForEntity |
(int dim, int tag, vec<int> &physTags) |
获取实体所属物理组标签列表 |
model::getPhysicalName |
(int dim, int tag, string &name) |
获取物理组名称 |
model::getPartitions |
(int dim, int tag, vec<int> &partitions) |
获取实体所属分区索引列表 |
model::getParent |
(int dim, int tag, int &parentDim, int &parentTag) |
获取分区实体的原始父实体 |
22.5.4 数据结构速记
| 概念 | 存储方式 | 索引公式 |
|---|---|---|
| 节点坐标 | coords[x0,y0,z0, x1,y1,z1, ...] |
x_i = coords[3*i], y_i = coords[3*i+1], z_i = coords[3*i+2] |
| 单元连接性(getElements) | nodeTags[typeIdx] 为展平一维数组 |
第 j 个单元节点起始于 j * numNodesPerElem |
| 单元连接性(getElementsByType) | nodeTags 为展平一维数组 |
同上,起始于 j * numNodesPerElem |
| 实体标识 | pair<int,int> 或两个独立 int |
(dim, tag) |
| 参数坐标 | paramCoord[u0,v0,w0, u1,v1,w1, ...] |
按 numNodes * 3 交错(仅曲面/体有参数坐标) |
22.5.5 典型前处理工作流
1. gmsh::initialize() // 启动 Gmsh
2. gmsh::open(file) 或 手动建立几何 // 加载/创建模型
3. model::getEntities(entities) // 获取实体列表
4. 遍历 entities:
4a. mesh::getNodes(..., dim, tag) // 提取节点
4b. mesh::getElements(..., dim, tag) // 提取单元
4c. getAdjacencies(dim, tag, ...) // 查询拓扑
4d. getPhysicalGroupsForEntity(...) // 识别边界条件
4e. getElementProperties(...) // 理解单元结构
5. 重组为求解器数据格式 // 构建 CSR/COO 等
6. gmsh::clear(); gmsh::finalize() // 清理
本章覆盖了 Gmsh C++ API 中最核心的前处理查询接口。通过 getEntities() + getNodes() + getElements() 的三步模式,可以完整提取模型中的所有网格数据。配合 getAdjacencies() 的拓扑查询和 getPhysicalGroupsForEntity() 的物理组识别,能够胜任绝大多数有限元前处理软件的数据准备需求。下一章将介绍如何使用 API 直接修改和操作网格。