
简介这份PDF是面向风工程与计算流体力学初学者的OpenFOAM入门培训讲稿由南京工业大学OpenFOAM研讨小组整理适合刚接触开源CFD、希望系统了解软件架构与设计理念的高校学生和科研人员。内容从OpenFOAM的历史沿革讲起梳理其与帝国理工学院Gosman小组、Charlie Hill博士论文及Henry Weller、Hrvoje Jasak等人的渊源并重点剖析有限体积离散、非结构化多面体网格、面向对象类封装、大规模并行计算等核心特性还涉及自动网格运动、拓扑变化、拉格朗日粒子追踪、有限元与有限面积离散等高级功能以及实时选择表定制、分层开发与代码重用等设计理念。资源包为单个PDF文件大小约162KB轻量便于随时查阅。目前已有552人学习下载可作为理解OpenFOAM整体框架、把握其面向对象数值库思路的入门参考。1. 风工程仿真为什么绕不开 OpenFOAM 这个黑匣子做风工程的人迟早会撞上一个尴尬建筑表面风压、行人高度风速、屋盖绕流这些事商业软件能算但一旦要改湍流模型、换入口风剖面、批量跑几十个工况授权和黑箱就成了拦路虎。OpenFOAM 正好卡在这个痛点上——它是一套开源的计算流体力学工具箱风工程里最常被拿来算大气边界层流动、钝体绕流和风压分布。这份基础培训材料瞄准的就是刚接触它的人你懂流体力学但面对一堆字典文件不知道从哪下手。它解决的不是会不会算而是能不能自己掌控从网格到后处理的每一步。适合结构风工程、建筑通风、桥梁气动方向的从业者尤其是被商业软件锁死、想自己搭一套可复现流程的人。2. 先搞懂 OpenFOAM 的组织逻辑它不是一个软件是一堆工具很多人第一次装完 OpenFOAM敲了个命令没反应就以为装坏了。其实它的设计哲学和商业软件完全不同理解这一点比记命令重要得多。2.1 求解器、字典、工具三分天下OpenFOAM 把一次仿真拆成三块求解器负责算字典文件负责告诉它怎么算前后处理工具负责准备和看结果。风工程常用的求解器是simpleFoam稳态不可压和pimpleFoam瞬态不可压前者算平均风压够用后者算涡脱落、脉动风压才需要。字典文件放在算例目录的三个子文件夹里0/放初始和边界条件constant/放网格和物性system/放求解控制。这个结构是死的OpenFOAM 靠目录名找文件你把0改成zero它就不认了。我一般建议新手先把一个自带算例完整跑通再动自己的几何否则连报错都看不懂。# 查看当前安装版本和可用求解器 foamVersion ls $FOAM_SOLVERS/incompressible/foamVersion输出的是环境变量里的版本号不同版本字典语法有差异风工程里simpleFoam的fvSolution写法在较新版本里改过跨版本抄配置是翻车高发区。$FOAM_SOLVERS是安装时写进环境变量的路径列出来能确认你的求解器到底装没装全。2.2 环境变量是它的命门OpenFOAM 不靠注册表也不靠图形界面找自己全靠环境变量。你每开一个新终端都得先 source 一次配置脚本否则敲blockMesh就是 command not found。这不是 bug是它的运行方式。# 每次新终端都要执行路径按实际安装位置改 source /opt/openfoam/etc/bashrc # 验证是否生效 echo $WM_PROJECT_DIR which blockMeshsource那行的路径是安装根目录下的etc/bashrc不同打包方式位置不同有的在/usr/lib/openfoam下。echo $WM_PROJECT_DIR能打印出项目根目录说明生效了which blockMesh能定位到可执行文件。如果这两条有一个空后面所有操作都别做先解决环境。提示把 source 那行写进~/.bashrc最省事但如果你同时装了多个版本会互相覆盖风工程里版本混用导致的诡异报错能查一整天。2.3 算例目录的复制式工作流OpenFOAM 没有新建工程按钮标准做法是从教程目录复制一个最接近的算例过来改。教程在$FOAM_TUTORIALS下风工程相关的钝体绕流可以看incompressible/simpleFoam里的例子。# 复制一个稳态不可压算例到自己的工作目录 cp -r $FOAM_TUTORIALS/incompressible/simpleFoam/pitzDaily $HOME/windCase cd $HOME/windCase # 先原样跑一遍确认环境没问题 blockMesh simpleFoamcp -r递归复制整个算例目录pitzDaily是个经典的后台阶流动例子结构完整、网格简单适合验证环境。blockMesh根据system/blockMeshDict生成网格simpleFoam直接跑求解。原样跑通再改这是排查是环境问题还是我配置问题的唯一可靠分界线。跑完你会看到终端刷迭代残差最后输出End算例目录里多出时间步文件夹。3. 风工程算例从零搭起网格、边界、求解控制跑通教程只是热身真正要算自己的建筑或地形得从几何到边界条件全部自己配。这一章按实际操作顺序走一遍。3.1 用 blockMesh 搭一个可用的计算域风工程计算域有讲究入口到建筑要留够发展距离出口要留够尾流恢复距离顶部和侧面要避免阻塞。常见做法是入口距建筑 5 倍建筑高度出口 15 倍侧面和顶部各 5 倍。域太大网格量爆炸太小结果不可信这个比例是血泪经验攒出来的。# system/blockMeshDict 里定义背景网格下面是关键片段 vertices ( (-50 -50 0) // 0 入口下左 (150 -50 0) // 1 出口下左 (150 50 0) // 2 出口下右 (-50 50 0) // 3 入口下右 (-50 -50 100) // 4 顶部四点 (150 -50 100) (150 50 100) (-50 50 100) ); blocks ( hex (0 1 2 3 4 5 6 7) (60 20 20) simpleGrading (1 1 1) );vertices定义八个角点坐标单位是米这里域是 200×100×100。blocks里hex后面跟八个顶点编号顺序不能乱(60 20 20)是三个方向的网格数simpleGrading控制网格拉伸全 1 表示均匀。风工程里靠近地面要加密可以把第三个方向的 grading 改成(1 1 4)让底层更密但别一上来就拉太狠网格长宽比过大会让求解器发散。3.2 入口风剖面和地面粗糙度怎么设大气边界层风剖面是风工程的核心输入。规范里常用幂律或对数律OpenFOAM 里通过0/U的入口边界条件实现。对数律更贴近物理但幂律在工程里更常见。// 0/U 里的入口边界用 codedFixedValue 实现幂律剖面 inlet { type codedFixedValue; value uniform (0 0 0); name powerLaw; code #{ const scalar Uref 10.0; // 参考高度风速 const scalar Zref 10.0; // 参考高度 const scalar alpha 0.16; // 地面粗糙度指数 const vectorField Cf patch().Cf(); vectorField U *this; forAll(Cf, i) { scalar z max(Cf[i].z(), 0.5); // 避免地面除零 U[i] vector(Uref*pow(z/Zref, alpha), 0, 0); } #}; }codedFixedValue允许在字典里直接写 C 代码编译后作为边界条件。Uref和Zref是参考风速和高度alpha是地面粗糙度指数城市中心取 0.3 左右开阔地取 0.14 到 0.16。Cf是面上单元中心坐标循环里按高度算风速。max(Cf[i].z(), 0.5)是防止地面附近 z 趋近零导致幂运算出问题这个 0.5 是经验下限。地面边界用nutkWallFunction配合kqRWallFunction入口的湍动能k按1.5*(U*I)^2估湍流强度I取 0.1 到 0.2。3.3 fvSchemes 和 fvSolution 里必须改的几个参数默认的格式对简单流动够用但风工程里对流项离散格式直接决定结果可信度。一阶迎风太耗散会把涡抹平建议用limitedLinearV或linearUpwind。// system/fvSchemes 关键片段 divSchemes { div(phi,U) Gauss linearUpwind grad(U); } // system/fvSolution 关键片段 SIMPLE { nNonOrthogonalCorrectors 1; } relaxationFactors { equations { U 0.7; k 0.7; epsilon 0.7; } }linearUpwind是二阶迎风格式比一阶精度高但稳定性差一点配合grad(U)梯度限制。nNonOrthogonalCorrectors 1处理网格非正交风工程里地形网格非正交度高这个值可能要加到 2 到 3。松弛因子0.7是稳态求解的常用值发散时先降到 0.5 再试。残差收敛标准别只看默认的 1e-4风压系数稳定了才算收敛我一般同时监控建筑表面几个点的压力。4. 跑起来之后监控、后处理和结果可信度判断算完不等于算对。风工程结果要经得起和规范、风洞数据对照这一章讲怎么判断你的结果能不能用。4.1 残差之外必须监控物理量残差降下去但结果发散的情况太常见了。稳态求解里我习惯在system/controlDict里加functionObjects监控建筑表面压力和几个特征点风速。// system/controlDict 里加监控 functions { pressureProbe { type probes; libs (libsampling.so); fields (p U); probeLocations ( (0 0 10) // 建筑迎风面某点 (20 0 10) // 尾流区某点 ); writeControl timeStep; writeInterval 50; } }probes是采样工具libs加载采样库fields指定采哪些场probeLocations是监控点坐标。writeInterval 50表示每 50 步写一次稳态算例里这个值别太小否则文件刷太快。跑完后postProcessing/probes/下会有数据文件用脚本画出来看是否走平。走平了才算收敛只看残差是自欺欺人。4.2 风压系数提取和参考值换算风工程最终要的是风压系数CpOpenFOAM 算出来的是压力p需要换算。不可压求解器里p是运动压力单位是 m²/s²要乘密度才是帕斯卡。# 用 foamCalc 或 postProcess 提取建筑表面压力 postProcess -func patchAverage(p, building) # 手动换算 Cp 的公式 # Cp (p - p_ref) / (0.5 * U_ref^2)patchAverage对指定 patch 求平均压力building是你几何里建筑表面的 patch 名。换算时p_ref取远场参考压力U_ref取参考高度风速。注意 OpenFOAM 的p已经除以密度所以Cp公式里分母直接用0.5*U_ref^2不用再乘密度。这个细节搞错结果差一个量级而且不容易发现。4.3 网格无关性验证怎么做才不浪费时间网格无关性不是把网格翻倍再算一遍那么简单。风工程里我一般做三套粗、中、细网格量按 1.5 到 2 倍递增比较建筑表面平均Cp和尾流长度。如果中网格和细网格差在 5% 以内中网格就够用。网格级别单元数表面平均 Cp尾流再附长度粗50 万0.723.2H中120 万0.683.8H细250 万0.673.9H中细差 1.5%说明中网格可用。粗网格差 6%不能用。这个表是判断依据不是让你照抄数字你的几何和来流不同绝对值会变但趋势判断方法一样。做三套网格的时间成本高但比拿一个不可信结果去汇报强。5. 避坑风工程 OpenFOAM 最常见的五个翻车点这一章全是踩过的坑每条按现象、原因、解决写能帮你省下大量试错时间。5.1 求解发散残差飙到 NaN现象跑了几十步残差突然跳到nan或inf终端刷一堆bounding警告。原因通常是网格质量差、时间步太大或松弛因子过高。先查checkMesh看有没有负体积或高非正交面。解决checkMesh输出里Max non-orthogonality超过 70 就要处理网格simpleFoam先把松弛因子降到 0.5fvSchemes里对流项临时换upwind跑通再换回来。5.2 入口风剖面设了但结果不对现象入口边界明明写了幂律但建筑表面风压分布和预期反了。原因多半是坐标方向搞错或者codedFixedValue没编译成功静默用了默认值。解决跑之前在入口 patch 上采样看U分布确认风向和大小codedFixedValue编译失败会在 log 里报错别只看终端最后几行。5.3 收敛了但 Cp 和规范差很远现象残差降到 1e-5监控点也走平了但Cp比规范值大 30%。原因通常是参考风速和参考高度取错或者p的参考值没设对。解决确认Uref和Zref与规范一致检查0/p里有没有设pRefValue不可压求解器里压力是相对的参考点选错整体平移。5.4 并行跑完结果和单核不一样现象单核跑的结果和mpirun -np 8跑的对不上。原因一般是并行分解后边界条件处理不一致或者decomposeParDict的分块方式导致某些 patch 被切开。解决并行前后都做checkMesh对比网格量decomposeParDict里method scotch比simple更均衡风工程里几何不规则时优先用 scotch。5.5 后处理采样点取在了建筑内部现象probes采出来的速度一直是零。原因监控点坐标落在了建筑实体内部OpenFOAM 对内部点不插值直接给零。解决采样前用paraFoam看一眼几何位置或者把点稍微挪到流场区域。这个坑很隐蔽因为不报错只是数据没意义。6. 把风工程算例做成可复用的模板跑通一个算例只是开始真正省时间的是把它变成模板。我一般会把0、constant、system三个目录里所有跟具体几何无关的配置抽出来几何相关的用脚本参数化。比如入口风剖面的Uref、alpha网格的域尺寸都写成变量放在一个config文件里用sed或 Python 脚本替换。#!/bin/bash # runCase.sh 参数化跑算例 Uref${1:-10.0} alpha${2:-0.16} sed -i s/Uref .*/Uref $Uref;/ 0/U sed -i s/alpha .*/alpha $alpha;/ 0/U blockMesh log.blockMesh 21 checkMesh log.checkMesh 21 simpleFoam log.simpleFoam 21 postProcess -func patchAverage(p, building) log.cp 21这个脚本接收两个参数默认值 10 和 0.16用sed替换0/U里的对应行然后依次跑网格、检查、求解、后处理每步日志单独存。这样换工况只改参数不用动字典。sed -i直接改原文件跑之前记得备份或者用模板文件复制一份再改。验证模板是否可靠我有个习惯拿一个已经有风洞数据的标准钝体案例用模板跑一遍对比Cp分布。如果对得上模板才敢用于新几何。这个验证步骤不能省模板里的一个默认参数错了后面所有算例都错而且错得一致反而更难发现。最后说个教训我早期图省事直接拿别人的算例改几何没检查fvSchemes里的离散格式结果算出来的尾流比风洞数据短了一半查了两天才发现是格式太耗散。从那以后任何算例接手先看fvSchemes和fvSolution再看几何。这个习惯帮我省了无数后悔药。希望帮到你。本文还有配套的精品资源点击获取