跳转至

第7章 uFVM 与 OpenFOAM® 中的有限体积网格(The Finite Volume Mesh in OpenFOAM® and uFVM)

作者

本章由 F. Moukalled、L. Mangani 和 M. Darwish 合著。本章是 Ch 6 网格规范的"实现篇" —— 把"理论上 FVM 网格需要什么信息"转化为"在 uFVM(MATLAB 教学代码)与 OpenFOAM(C++ 工业代码)这两套代码中,具体怎么存储、怎么读取、怎么处理"。本章是全书"工程实用价值"最高的一章之一。

内容概述

本章的核心目标是把 Ch 6 抽象的 FVM 网格规范,落到两套具体代码的数据结构与文件组织上。

§7.1 uFVM —— 教学性、MATLAB 写成的非结构 FVM 代码。uFVM 共享 OpenFOAM 的核心数据结构(mesh fields + boundary conditions),但用更简单的实现技术。

§7.1.1 OpenFOAM 测试用例 —— OpenFOAM 的标准测试用例组织为 3 个目录: - 0/(或 0.orig/):时间步 0 时的场初始化与边界条件(UpT 等) - constant/:物理属性(transportProperties)+ 网格(polyMesh/) - system/:求解控制(controlDictfvSchemesfvSolution

OpenFOAM 的著名 cavity 算例(顶盖驱动方腔流)是入门示例,验证 uFVM 的网格读取功能。

§7.1.2 polyMesh 目录 —— 5 个核心文件: - points:cell 顶点的 \((x, y, z)\) 坐标列表 - faces:face 的顶点索引列表(每个 face 由若干顶点构成) - owner:每个 face 的 owner cell 索引(内部面 + 边界面都有 owner) - neighbour:内部面的 neighbour cell 索引(边界面的 neighbour = -1) - boundary:边界 patch 列表(name、type、nFaces、startFace)

§7.1.3 uFVM 网格读取 —— uFVM 通过 cfdReadOpenFoamMesh 脚本读取 OpenFOAM 网格,存储为 MATLAB struct: - m.nodes:每个 node 的 centroid、index、iFaces、iElements - m.faces:每个 face 的 iNodes、iOwner、iNeighbour、centroid、Sf、area、CN、geoDiff、T、gf、walldist - m.elements:每个 cell 的 index、iNeighbours、iFaces、iNodes、volume、faceSign - m.boundaries:patch 名、起始 face 索引、face 数量

§7.2 OpenFOAM —— 工业级、C++ 写成的开源 FVM 代码。OpenFOAM 的 polyMesh 类(src/OpenFOAM/meshes/polyMesh/)实现了与 uFVM 等价的网格数据结构,但用 C++ 类 + 模板 + 智能指针实现。

§7.2.1 OpenFOAM 测试用例的扩展 —— 除了 0/constant/system/,OpenFOAM 还有: - constant/dynamicMeshDict:动网格配置 - system/blockMeshDict:blockMesh 网格生成配置 - system/snappyHexMeshDict:snappyHexMesh 网格生成配置 - system/fvSchemes:离散化格式选择(gradScheme、divScheme、laplacianScheme、interpolationScheme 等) - system/fvSolution:求解器选择(SIMPLE、PISO)、线性求解器、容差、亚松弛因子

§7.2.2 OpenFOAM 的场与方程组装 —— OpenFOAM 的 GeometricField<Type, PatchField, GeoMesh> 模板类实现了 FVM 场存储;fvMatrix<Type> 类实现了 FVM 线性系统组装(与 Ch 5 Eq. 5.43 完全对应)。fvm::div(phi, U)fvm::laplacian(nu, U)fvm::ddt(U) 等显式操作符对应 Ch 8-14 的各项离散化方法。

§7.3 场的数据结构 —— uFVM 的 cfdFieldcfdMesh 与 OpenFOAM 的 GeometricFieldpolyMesh 的对应关系。

§7.4 边界条件 —— uFVM 的 cfdBoundary 与 OpenFOAM 的 fvPatchField 的对应关系。fixedValuefixedGradientzeroGradientmixedcyclicsymmetryPlane 等边界条件类型在两套代码中的实现方式。

§7.5 线性系统的存储 —— 稀疏矩阵的 CSR / CSC / COO 存储格式。OpenFOAM 使用 lduAddressing(Lower-Diagonal-Upper addressing)存储稀疏矩阵,相比 CSR 更适合非结构网格的 FVM 离散化。

§7.6 闭包 —— 本章的"代码实现视角"是 Ch 8-14 各项数值方法实现的"前置基础"。

核心方程与概念

本章以数据结构与文件格式为主,公式较少,但每个公式都是工业 CFD 实践的关键。

一、OpenFOAM 测试用例的目录结构(Fig. 7.1, §7.1.1)

cavity/
├── 0/                       # 时间步 0 的场初始化
│   ├── U                   # 速度场
│   └── p                   # 压力场
├── constant/
│   ├── transportProperties # 黏度等
│   └── polyMesh/           # 网格
│       ├── points
│       ├── faces
│       ├── owner
│       ├── neighbour
│       └── boundary
└── system/
    ├── controlDict         # 时间步长、起止时间
    ├── fvSchemes           # 离散格式
    └── fvSolution          # 求解器

二、polyMesh 5 文件的格式(§7.1.2, Listing 7.1-7.11)

  • points:每行一个 \((x, y, z)\),如 (32 16 0.9377383239)。header 标 nPoints
  • faces:每行一个 face,由若干顶点索引构成,如 4(36 573 589 52)。header 标 nFaces
  • owner:每行一个 cell 索引,对应 face 的 owner。nCells 是最大 owner 索引 + 1。
  • neighbour:每行一个 cell 索引,对应内部 face 的 neighbour(边界面对应 -1)。header 标 nInternalFaces
  • boundary:patch 列表,每 patch 包含 name、type、nFaces、startFace。

三、uFVM 数据结构(§7.1.3, Listing 7.13-7.17)

每个 node 存储: - centroid\((x, y, z)\) 坐标 - index:node 编号 - iFaces:相邻 face 索引列表 - iElements:相邻 element 索引列表

每个 face 存储: - iNodes:构成 face 的 node 索引列表 - iOwner:owner cell 索引 - iNeighbour:neighbour cell 索引(边界面 = -1) - centroidSfarea:几何量 - CNTgeoDiffgfwalldist:距离向量与几何因子

每个 element 存储: - iNeighboursiFacesiNodes:邻接关系 - volumecentroid:几何量 - faceSign:标志 element 在每个 face 上是 owner (+1) 还是 neighbour (-1)

四、稀疏矩阵存储的 ldu 格式(§7.5)

OpenFOAM 使用 lduMatrix(Lower-Diagonal-Upper Matrix)存储稀疏矩阵,相比通用的 CSR 格式,更适合 FVM 的非结构网格: - 对角元素存储为稠密数组 - 非对角元素按"owner + neighbour"对应存储 - 通过 lduAddressing 数组(lowerAddrupperAddr)索引非对角元素

lduMatrix 的存储结构与 Ch 5 Eq. 5.43 的 \(a_C \phi_C + \sum_F a_F \phi_F = b_C\) 形式直接对应 —— 每个 cell 的"对角系数"是 \(a_C\),"上对角 + 下对角"非零元素对应 \(\sum_F a_F\)。对角占优要求

\[\frac{|a_C|}{\sum_F |a_F|} \geq 1 \tag{7.1}\]

这是 FVM 离散化解的存在唯一性与稳定性的必要条件(Ch 5.4 节有界性原则)。

五、OpenFOAM 的显式离散算符(§7.2.2)

  • fvm::ddt(phi):瞬态项离散(Ch 13),对应

$\(\frac{\partial \phi}{\partial t}\bigg|_P \approx \frac{\phi_P^{n+1} - \phi_P^n}{\Delta t}\)$

  • fvm::div(flux, phi):对流项离散(Ch 11-12),对应

$\(\oint_{\partial V_P} \rho \mathbf{v} \phi \cdot d\mathbf{S} = \sum_f \rho \mathbf{v}_f \phi_f \cdot \mathbf{S}_f\)$

  • fvm::laplacian(coeff, phi):扩散项离散(Ch 8),对应

$\(\oint_{\partial V_P} \Gamma \nabla \phi \cdot d\mathbf{S} = \sum_f \Gamma_f \nabla \phi_f \cdot \mathbf{S}_f\)$

  • fvc::grad(phi):梯度显式计算(Ch 9),对应

$\(\nabla \phi_P = \frac{1}{V_P} \sum_f \phi_f \mathbf{S}_f\)$

每个算符返回一个 fvMatrix<Type>,可直接组装为线性系统 \(\mathbf{A} \mathbf{x} = \mathbf{b}\) 通过线性求解器(Ch 10)求解。

关键结论

  1. OpenFOAM 与 uFVM 在数据结构上高度同构:都基于"节点 → 面 → 控制体"三层拓扑,加上 owner / neighbour 关系与几何量存储。这种"数据结构同构"是 uFVM 能直接读取 OpenFOAM 网格的根本原因。
  2. OpenFOAM 的 polyMesh 5 文件是 FVM 网格的最小完备集pointsfacesownerneighbourboundary 这 5 个文件足够推导出 Ch 6 列举的所有几何量与拓扑关系。其他所有"派生量"(面积向量、距离向量、形心、体积)都由这 5 个文件计算。
  3. lduMatrix 存储格式适合 FVM:相比通用的 CSR 格式,ldu 格式直接对应 Eq. 5.43 的"对角 + 上对角 + 下对角"结构,对 FVM 离散化的矩阵组装与求解更友好。
  4. OpenFOAM 的 fvm:: / fvc:: 命名空间fvm::(隐式)返回 fvMatrixfvc::(显式)返回 GeometricField。这种命名约定清晰地分离了"参与线性系统组装的项"和"显式计算的项",是 OpenFOAM API 的核心设计。
  5. boundary patch 的 type 决定了边界条件的实现fixedValue / fixedGradient / zeroGradient / mixed / cyclic / symmetryPlane 等 patch type 与 Ch 5 §5.5 的边界条件处理规则一一对应。Ch 18 会详细讨论 OpenFOAM 的边界条件实现机制。

挑战和开放性问题

  1. 大数据量网格的 I/O 性能 —— OpenFOAM 网格以 ASCII 文本存储,工业级 CFD 算例的网格可能包含数亿 cell,I/O 成为瓶颈。OpenFOAM 提供 foamFormat binary 选项可显著加速,但兼容性较差。
  2. 稀疏矩阵求解器的预条件子 —— OpenFOAM 6+ 引入 PETSc / AMGCL 等外部求解器,但默认 GAMG(Geometric-Algebraic Multigrid)在某些病态问题上仍收敛困难。
  3. 并行 IO 与网格分解 —— 大规模并行 CFD 中,网格分解(scotch、metis、kahip)、并行 IO(HDF5、SST)的实现细节是工业 CFD 的关键,本书未深入。
  4. 动网格数据结构 —— OpenFOAM 的 dynamicMotionSolverFvMeshdynamicRefineFvMesh 等动网格实现涉及复杂的拓扑变化数据结构,本书未展开。
  5. GPU 加速 —— OpenFOAM 在 2016 年仍以 CPU 为主,GPU 加速(如 AMGXcuPDE)是后续发展方向,本书未涉及。
  6. cellZone / faceZone / pointZone —— OpenFOAM 的 zone 机制(用于区分流体 / 固体区域、转子 - 静子交界面等)未在本书展开。

个人反思与批判性分析

本章是全书"工程实用性"密度最高的一章,给出 uFVM 与 OpenFOAM 的完整数据结构与文件组织。本章对 OpenFOAM 用户的价值在于:OpenFOAM 的官方文档虽然完备,但很少系统性地把"为什么 OpenFOAM 要这样组织 mesh 数据"讲清楚。本章恰好填补了这一空白。

从写作特点看:

  • "教学代码 + 工业代码"双轨对比 —— uFVM 与 OpenFOAM 的数据结构一一对应(MATLAB struct ↔ C++ class),读者可以同时在两套代码上验证同一数值方法。这种"理论 → 教学实现 → 工业实现"的三级递进是 Moukalled 这本教材的核心教学设计。
  • polyMesh 5 文件的"最小完备集"思想 —— 本章把 OpenFOAM 看似复杂的网格数据结构简化为 5 个文件,每个文件的格式、header、示例都清晰展示。这对 OpenFOAM 自定义 solver 开发者是必备知识。
  • MATLAB struct vs C++ class 的设计哲学对比 —— uFVM 的 struct 字段名是字符串,运行时刻可动态修改;OpenFOAM 的 class 字段名是编译时确定的,运行时刻不可修改。这种"动态 vs 静态"的设计哲学对比,对学习"教学代码 → 工业代码"的过渡非常有价值。

但本章也存在不足:

  • OpenFOAM 的 GeometricField 模板类没有完整展开 —— GeometricField<Type, PatchField, GeoMesh> 三个模板参数的含义(Type = scalar/vector/tensor、PatchField = boundary condition 类、GeoMesh = volMesh/surfaceMesh/pointMesh)未详细解释。这是 OpenFOAM 自定义场类型开发的关键。
  • lduMatrix 与稀疏矩阵求解器的关系 —— 本章给出 lduMatrix 的存储结构,但未详细说明它如何与 PCGGAMGPBiCG 等线性求解器(Ch 10 详述)配合使用。
  • 对 OpenFOAM 第三方库(CGAL、PETSc、METIS、Scotch)的接口未提及 —— 工业级 OpenFOAM 使用涉及大量第三方数学库,本书完全未提及。
  • 缺少对 mapFieldssetFieldsfunkySetFields 等网格操作工具的介绍 —— 这些是 OpenFOAM 网格与场初始化 / 转换的核心工具。

总体而言,本章是 OpenFOAM 工程实践的"入门百科",对需要进入 OpenFOAM 二次开发(自定义 solver、自定义边界条件、自定义湍流模型)的读者是必读章节。本章与 Ch 6 一起构成 FVM 网格的"理论 + 实践"完整闭环。

重要参考文献

  • [X1] OpenFOAM Foundation (2014) The Open Source CFD Toolbox — User Guide. (OpenFOAM 官方文档)
  • [X2] OpenFOAM Foundation (2014) OpenFOAM: The Open Source CFD Toolbox — Programmer's Guide. (OpenFOAM 内部数据结构与 API)
  • [X3] Jasak H. (1996) Error Analysis and Estimation for the Finite Volume Method with Applications to Fluid Flows. PhD Thesis, Imperial College. (OpenFOAM 早期开发者的博士论文,OpenFOAM 数据结构与 FVM 离散化误差的原始设计文档)
  • [X4] Weller H.G., Tabor G., Jasak H., Fureby C. (1998) A tensorial approach to computational continuum mechanics using object-oriented techniques. Computers in Physics, 12(6): 620-631. (OpenFOAM 早期论文,介绍面向对象的 FVM 实现)
  • [X5] Moukalled F., Mangani L., Darwish M. (2016) uFVM source code. Available at: https://feaweb.aub.edu.lb/research/cfd. (uFVM 官方下载链接)
  • [X6] Geuzaine C., Remacle J.F. (2009) Gmsh: a three-dimensional finite element mesh generator with built-in pre- and post-processing facilities. International Journal for Numerical Methods in Engineering, 79(11): 1309-1331. (Gmsh 网格生成工具)
  • [X7] Karypis G., Kumar V. (1998) METIS: A Software Package for Partitioning Unstructured Graphs, Partitioning Meshes, and Computing Fill-Reducing Orderings of Sparse Matrices. University of Minnesota. (METIS 网格分解工具)
  • [X8] Balay S., et al. (2019) PETSc Users Manual. Argonne National Laboratory. (PETSc 求解器库)