
简介这份 OpenFOAM 入门学习资料面向零基础到初级水平的 CFD 学习者围绕开源流体计算软件的命令行操作、求解器选择与典型算例展开帮助读者建立从算例结构、离散格式到前后处理的整体认识。压缩包共 1 个 docx 文件约 55.87MB内容以图文笔记形式整理便于按知识点查阅和复习。资料已有 1144 人学习说明其对入门阶段具有一定参考价值。正文覆盖 alias 命令、库函数与 ODE、Cavity Flow 算例结构、时间与对流及 Laplacian 离散格式、relTol 与 tolerance 等求解器参数并梳理 checkMesh、setFields、refineMesh 等前处理工具和 co、vorticity、yPlus、sample 等后处理工具还涉及 Function Objects、forces 与力系数计算、probe 采样及常见边界条件类型可辅助读者理解 OpenFOAM 的目录组织、参数含义和基础使用流程。1. 从一次 cavity 算例跑崩说起这套入门笔记补的是哪一段装完 OpenFOAM 的第一天多数人卡在同一处blockMesh 跑通、icoFoam 跑完paraFoam 打开却是一片空白或者残差曲线跑到第三秒就翘头。这套 OpenFOAM 入门资料处理的正是这段最费试错的链路——alias 与求解器入口、src 下的库函数与 ODE、cavity 算例结构与离散格式、Utilities 前后处理、Function Objects 在线输出、边界条件与湍流模型最后落到 icoFoam 与 interFoam 的代码走读。它适合能敲命令但还没把算例调到收敛的人纯新手照着步骤能跑通 cavity但得先有有限体积法的概念不然参数为什么这么填只能靠背。2. 环境变量与命令入口alias、求解器、src 三层怎么串起来OpenFOAM 用起来别扭很大一部分不是物理问题是路径问题。它把可执行程序、算例库、源码树分散在几个环境变量指向的目录里版本一换路径就变新手很容易在cd上耗掉半天。这一章先把入口固定下来再谈求解。2.1 alias 不是语法糖是路径纪律先确认环境变量有没有生效。打开终端不要急着进算例先看这三条# 确认当前加载的是哪个版本、算例库和用户工作目录在哪 echo $WM_PROJECT_VERSION # 版本号例如 9、10、2306 echo $FOAM_TUTORIALS # 官方算例根目录路径很长的那个 echo $FOAM_RUN # 用户自己的 run 目录通常是 $HOME/OpenFOAM/$USER-x.y/run如果这三条输出为空说明etc/bashrc没被 source后面的命令全都会报 command not found。常见做法是把source $安装路径/etc/bashrc写进~/.bashrc登录即生效。路径确认完再谈 alias。我一般会在~/.bashrc里加这么几行# 写进 ~/.bashrcsource 一次或重开终端生效 alias foamcd $FOAM_RUN # 回工作目录避免每次手敲长路径 alias tutcd $FOAM_TUTORIALS # 回官方算例库抄写法用 alias srccd $FOAM_SRC # 回源码树读方程实现用 alias cleanfoamCleanCase -full # 清时间步和中间文件保留 0/constant/system alias lstfoamListTimes -latestTime # 看最后写出的时刻 alias tailogtail -n 40 log.* # 一眼看最近一次求解日志尾巴这几个别名的价值不在省几个字符而在把「我永远从这几个根目录出发」变成肌肉记忆。翻车最多的情况是在 A 算例目录里改了fvSchemes却跑到 B 目录去执行icoFoam日志看起来正常结果全是旧的。foamCleanCase -full在部分旧版本里叫foamCleanPolyMesh敲不出来就先which foamCleanCase确认一下别硬猜。2.2 求解器在 app方程在 srcODE 是第三层OpenFOAM 的源码结构其实很规整记住三个位置就够用了目录变量里面是什么什么时候去翻$FOAM_APP各求解器主程序如 icoFoam、interFoam想知道某个求解器解了哪几个方程、读了哪些字典$FOAM_SRC有限体积离散、库函数、湍流模型、ODE 求解器想知道div、laplacian到底怎么实现kEpsilon 的方程怎么写的$FOAM_TUTORIALS覆盖各物理场景的官方算例不知道某个 function object 或边界条件怎么写时反查现成的用两条命令就能定位到具体文件# 找求解器主目录不同版本层级略有差异所以用 -maxdepth 限制深度 find $FOAM_APP -maxdepth 4 -type d -name icoFoam # 找湍流模型的实现文件kEpsilon 的 k 方程和 epsilon 方程都在同名 C 文件里 find $FOAM_SRC -name kEpsilon.C -o -name kEpsilon.H参数说明-maxdepth是防止在超大源码树里递归太深-name支持通配想一次找多个就在后面接-o。新版本把一部分求解器挪进了$FOAM_APP/modules如果第一条命令什么都没输出把-maxdepth去掉再试。至于 ODE也就是常微分方程那一层它不在有限体积主链路上但在反应、颗粒跟踪、某些后处理量的积分里会用到。$FOAM_SRC/ODE下有一整套显式/隐式积分器读它的意义在于当你写的自定义边界条件或源项里需要对某个标量沿时间积分不必自己从零写 RK4直接复用现成的类就行。2.3 把 cavity 跑起来四步链路cavity 是 OpenFOAM 的「Hello World」方腔顶盖驱动层流不可压网格小、算得快非常适合用来验证环境。链路只有四步# 1. 把官方算例复制到自己的工作目录别在算例库里直接改 cp -r $FOAM_TUTORIALS/incompressible/icoFoam/cavity/cavity $FOAM_RUN/ cd $FOAM_RUN/cavity # 2. 生成网格日志单独落到文件屏幕只留状态 blockMesh log.blockMesh 21 # 3. 求解 icoFoam log.icoFoam 21 # 4. 看结果时刻和日志尾巴 foamListTimes -latestTime tail -n 20 log.icoFoam逻辑说明 log.xxx 21是把标准输出和标准错误合并写进日志这是 OpenFOAM 的常规操作因为屏幕上滚得太快报错一闪就没。判断有没有算成功不看屏幕看日志末尾有没有End以及foamListTimes能不能列出非零时刻。如果blockMesh那一步就失败了先看log.blockMesh里是不是cannot find file blockMeshDict那说明你在错误的目录里执行回到算例根目录再跑。cavity 的controlDict默认endTime是 0.5deltaT是 0.005会写出若干个时刻。跑完你会在算例根目录看到0/、0.1/、0.2/一直到0.5/这些文件夹每个里面是同一批场文件在该时刻的快照。2.4 paraFoam 打不开算例时的那条 touch 命令这是最经典的一类问题求解日志一切正常时刻文件夹也都生成了双击paraFoam打开却什么都没有。原因不复杂——ParaView 需要一个后缀为.OpenFOAM的空文件作为「入口」靠这个后缀去加载 OpenFOAM 的 reader 插件而这个文件不会被求解器自动创建。# 方式一手工造一个空文件命名必须与算例目录同名 touch cavity.OpenFOAM # 方式二让 OpenFOAM 自己生成 .foam 文件较新版本推荐 paraFoam -touch # 方式三reader 插件没编译或加载失败时退一步转 VTK foamToVTK -latestTime参数说明.OpenFOAM文件的内容为空ParaView 只认文件名和后缀所以touch出来的文件放在算例根目录、与constant/、system/同级即可。paraFoam -touch生成的是.foam本质作用相同。foamToVTK -latestTime只转最后一个时刻想转全部就去掉这个参数代价是磁盘占用会明显变大。注意如果paraFoam命令本身报找不到说明对应的 ParaView 组件没装上这时候别死磕直接用foamToVTK转格式用任意 ParaView 打开.vtk系列文件功能上不差。3. cavity 算例的参数表时间离散、对流格式与残差容差怎么取cavity 跑通只是知道了流程真正决定「算得对不对、稳不稳」的是system/下那三个字典controlDict、fvSchemes、fvSolution。这一章把里面对新手最不友好、又最不能随便填的几项拆开。3.1 算例结构三个文件夹各管什么先把目录职责理清楚后面调参数才知道该改哪里。文件夹内容改动频率0/初始场与边界条件如U、p、k、epsilon换工况时改constant/polyMesh/网格、transportProperties物性、turbulenceProperties湍流开关换网格或物性时改system/blockMeshDict、controlDict、fvSchemes、fvSolution调数值时改一个常见的误会是把边界条件写在system/里。0/下的文件就是「场 边界」每个场文件末尾的boundaryField块才是边界条件真正生效的地方这一点在换求解器的时候尤其重要因为不同求解器要求的场文件不一样icoFoam 只要U和pinterFoam 还要alpha.water。3.2 时间离散Crank-Nicolson 的 θ 为什么常取 0.9// system/fvSchemes ddtSchemes { default CrankNicolson 0.9; }逻辑说明这个系数是一个加权因子1 表示纯 Crank-Nicolson时间上二阶但容易在陡梯度区域产生非物理振荡0 退化成欧拉一阶稳定但数值耗散大。取 0.9 相当于「九成二阶 一成欧拉」用一点点一阶耗散把振荡压住同时保留大部分时间精度所以很多教程和工程算例都默认这个值。backward也是二阶但在有界场问题里存在解的无界风险尤其是相分数、组分这类必须落在 [0,1] 的场一般不推荐拿来当默认。如果算例对时间精度要求不高、只求稳直接上Euler也没什么丢人的先把流场跑出来再谈精度比一开始就追求二阶然后炸掉划算。配CrankNicolson的时候controlDict里的deltaT和库朗数要一起看。cavity 这种量级默认deltaT 0.005就够换到真实几何先按特征尺寸除以特征速度估一个上限再留一半余量。3.3 对流项默认 none逼你逐项指定// system/fvSchemes divSchemes { default none; // 不设默认缺哪项直接报错 div(phi,U) Gauss linearUpwind grad(U); // 动量对流二阶迎风带梯度修正 div(phi,k) Gauss upwind; // 湍动能一阶保正 div(phi,epsilon) Gauss upwind; // 耗散率一阶保正 }参数说明default none是个刻意的设计——只要某个方程项没被显式指定求解器立刻报错停下而不是偷偷用一个可能不合适的格式。这比求解跑完了才发现结果不对要好得多。具体项怎么选取决于物理。动量方程用linearUpwind这类二阶迎风是因为一阶upwind的数值扩散会把涡抹平cavity 里的主涡会明显变小而k和epsilon这类必须非负的量用一阶upwind换稳定性是常见取舍。没有「最佳格式」只有「这一项在这个问题下能不能接受」。3.4 Laplacian 与梯度由 checkMesh 的正交性决定// system/fvSchemes gradSchemes { default Gauss linear; grad(U) cellLimited Gauss linear 1; // 限制梯度抑制极端网格上的过冲 } laplacianSchemes { default Gauss linear corrected; // 非正交修正 } snGradSchemes { default corrected; }逻辑说明corrected表示做完整的非正交修正网格质量好时精度最高网格歪得厉害完整修正反而会引入振荡这时候换成limited 0.33或limited 0.5更稳系数就是修正量的限幅比例。怎么判断该用哪个跑一次checkMesh看Max non-orthogonality。低于 60 用corrected基本没问题60 到 70 之间建议limited 0.5再高就得先改网格而不是调格式了。cellLimited ... 1里的 1 是限幅上限取 1 表示允许梯度在单元内线性重构取更小的值会更保守。3.5 relTol、tolerance、pRefCell三个最容易被乱填的参数// system/fvSolution solvers { p { solver PCG; preconditioner DIC; tolerance 1e-06; // 绝对残差到这个量级就停 relTol 0.05; // 相对残差比上一次降两个量级就停 } U { solver smoothSolver; smoother symGaussSeidel; tolerance 1e-05; relTol 0; // 置 0 表示关闭相对残差判据 } } PISO { nCorrectors 2; nNonOrthogonalCorrectors 0; pRefCell 0; // 压力参考单元编号 pRefValue 0; // 该单元上的压力参考值 }参数说明tolerance是绝对残差门槛relTol是相对残差门槛两者谁先满足谁生效relTol设为 0 就是彻底关掉相对判据只认绝对残差。实践里压力方程常用relTol 0.05因为 PISO 内层不需要把压力解到很准外层会再修正而速度场一般relTol 0避免内层偷懒导致连续性残差降不下去。pRefCell和pRefValue的存在是因为不可压求解里压力只出现在梯度中整体加一个常数不改变流场。所以 OpenFOAM 解出来的压力是相对值不是绝对值必须钉一个参考点。默认钉在 0 号单元、值取 0一般不用改但如果 0 号单元恰好在你要监测压力的位置记得把参考点挪走否则那个点的压力永远显示为 0看起来像 bug。nCorrectors是 PISO 的压力修正次数2 是常规值网格很差或者时间步很大时可以加到 3代价是单步耗时上升。4. Utilities 与 Function Objects把网格检查、采样和力矩输出固定成流程求解器之外OpenFOAM 还有一大批小工具用官方的话叫 utilities。这类命令的特点是单独看都很简单串成流程才知道哪个先哪个后。这一章按「前处理 → 后处理 → 在线输出」的顺序走一遍。4.1 checkMesh先看四个数再看 Mesh OK# 全量检查几何和拓扑都查日志落盘便于对比不同版本网格 checkMesh -allGeometry -allTopology log.checkMesh 21 # 只挑关心的指标出来看 grep -E non-orthogonality|skewness|aspect ratio|Min volume|Mesh OK log.checkMesh为什么强调「先看四个数再看 Mesh OK」Mesh OK只说明拓扑自洽、没有负体积这类硬错误不说明网格质量适合计算。真正的判断依据是下面这几个指标指标经验阈值超标后的典型后果Max non-orthogonality 65最好 60扩散项误差大残差抖动Max skewness 4最好 1对流项振荡局部发散Max aspect ratio边界层内可到几百外场 100收敛慢压力场出现条纹Min volume必须 0出现负体积直接无法计算动网格算例还有一个额外要求不能只在开始查一次。网格在运动过程中会不断变形中途质量崩掉是常态所以要在controlDict里挂一个checkMesh类的 function object或者定期手工查一次中间时刻。4.2 网格变换与局部加密transformPoints 加 topoSet/refineMesh# 平移单位与算例一致一般是米注意引号不能省 transformPoints -translate (0 0 -0.05) # 缩放参数是乘数不是目标尺寸0.001 表示毫米转米 transformPoints -scale (0.001 0.001 0.001) # 旋转两个向量分别定义旋转轴和参考方向 transformPoints -rotate (0 0 1) (0 1 0)这三个命令都有-overwrite变体不加时默认写回constant/polyMesh实际行为在不同版本略有差异动网格前建议先备份整个polyMesh目录。局部加密比全局加密复杂一档因为它需要两个字典配合。第一步用topoSet圈出要加密的区域// system/topoSetDict actions ( { name box1; // cellSet 名字下一步 refineMeshDict 要引用 type cellSet; action new; source boxToCell; box (0.02 0.02 0) (0.04 0.04 0.01); // 加密区域的包围盒 } );第二步让refineMesh读这个 cellSet// system/refineMeshDict refineMeshDict { coordinateSystem cartesian; useHexTopology true; geometricCut false; directions (1 1 1); // 三个方向是否切分1 表示切、0 表示不切 cells (box1); // 与 topoSetDict 里的 name 严格一致 }topoSet refineMesh -overwrite逻辑说明topoSet先跑成功后在constant/polyMesh/sets/下生成box1文件你可以直接打开确认单元数量对不对。-overwrite表示直接覆盖0/目录下的网格而不是新建一个时间步文件夹好处是省事坏处是改错了没法回退所以我一般先cp -r constant/polyMesh constant/polyMesh.bak。directions三个分量分别控制 x、y、z 方向是否切分。只加密流向就写(1 0 0)三个方向都切是(1 1 1)每次切分单元数翻倍三次就是八倍别一上来就全切。4.3 setFields 与 createBaffles初始相分布和内部面转边界setFields解决的是「初始时刻某一小块区域里是水、其余是空气」这类问题溃坝、气泡、射流都用得上。// system/setFieldsDict defaultFieldValues ( volScalarFieldValue alpha.water 0 ); // 全域默认是空气 regions ( boxToCell { box (0 0 0) (0.4 0.1 0.1); // 水的初始区域 fieldValues ( volScalarFieldValue alpha.water 1 ); // 该区域内相分数为 1 } );# 先把模板文件复制成真实场文件再执行 setFields 覆盖 cp 0/alpha.water.org 0/alpha.water setFields逻辑说明defaultFieldValues会被应用到整个计算域regions里的块再局部覆盖两者是「先铺底、再打补丁」的关系。alpha.water这种场在 interFoam 算例里通常以.org后缀存在必须先复制成正式文件名否则setFields找不到目标场会直接报错。createBaffles处理的是另一类需求把网格内部的某个面interior 或 interface转成真正的边界面比如薄壁、挡板、周期面。它同样依赖topoSet先建faceZone// system/createBafflesDict patches ( { name baffle1; // 生成的边界 patch 名 type faceZone; // 来源类型从 faceZone 取 zoneName fz1; // topoSetDict 里建的 faceZone 名 patchType wall; // 转换成什么类型的边界 } );createBaffles -overwrite参数说明patchType可以是wall、patch、cyclic等选错会导致后续边界条件类型对不上。-overwrite同样意味着直接改polyMesh这一步比加密更危险因为它会改变边界列表之前写好的0/场文件里的boundaryField条目会失效必须同步补上新的 patch 条目。4.4 后处理命令输出目录永远在 postProcessing 下OpenFOAM 的后处理命令有个统一约定结果不写进时间步文件夹而是写到算例根目录的postProcessing/下按「功能名/时刻/」分层。# 计算旋度输出到 postProcessing/vorticity/time/ postProcess -func vorticity -latestTime # 计算 yPlus输出到 postProcessing/yPlus/time/ postProcess -func yPlus -latestTime # 沿一条线采样需要先有 system/sampleDict postProcess -func sample -latestTime # 看看到底生成了什么 find postProcessing -type f | head -20逻辑说明老版本里vorticity、yPlus是独立命令新版本统一收进postProcess -func两种写法都在用敲不出来就用另一种。-latestTime只处理最后一个时刻做动画或分析瞬态过程时去掉这个参数会遍历所有已写出的时刻。采样需要sampleDict。如果在system/下没有这个文件sample命令会直接报错退出// system/sampleDict type sets; libs (libsampling.so); interpolationScheme cellPoint; setFormat raw; sets ( line1 { type uniform; // 均匀取点也可以用 cloud 自定义点集 axis x; // 采样线沿 x 方向 start (0 0.05 0.005); end (0.1 0.05 0.005); nPoints 100; } );参数说明start和end必须落在计算域内部落在边界外会得到空文件nPoints是采样点数量太小曲线会失真太大文件会膨胀。setFormat raw输出纯文本方便直接用 Python 或 Excel 读换成gnuplot之类的格式可以配合绘图工具直接出图。如果system/下出现sampleDict.swp这种文件说明之前有编辑器非正常退出残留的交换文件会让某些操作报错。rm -f sampleDict.swp删掉即可不影响结果。采样点固定、但又想看整个时间序列的情况用probes比反复跑sample划算。它是一个 function object写在controlDict里随求解过程同步输出// system/controlDict 末尾 functions { probes1 { type probes; libs (libsampling.so); writeControl timeStep; writeInterval 1; fields (p U); // 要监测的场按需增减 probeLocations ( (0.05 0.05 0.005) // 可以写多个点每行一个 ); } }参数说明writeInterval 1表示每个时间步都记一次粒度最细但文件也最大fields里写几个场输出文件里就有几列。probeLocations里的点不必是网格节点求解器会做插值。这种方式的代价是必须在线跑算完了再想加就得重算所以位置要提前想清楚。4.5 Function Objectsforces 与 forceCoeffs 怎么写进 controlDictforces算的是边界面上的力和力矩forceCoeffs在它的基础上再除以动压和参考面积得到升力系数、阻力系数。楼宇风场、翼型绕流这类算例基本绕不开。// system/controlDict 的 functions 块 functions { forces1 { type forces; libs (libforces.so); writeControl timeStep; writeInterval 1; patches (walls); // 参与积分的边界 patch CofR (0.05 0.05 0.005); // 力矩参考点影响力矩大小 rho rhoInf; // 不可压用 rhoInf rhoInf 1; // 密度值量纲要和算例一致 log true; // 同时打印到求解日志 } coeffs1 { type forceCoeffs; libs (libforces.so); patches (walls); CofR (0.05 0.05 0.005); rho rhoInf; rhoInf 1; liftDir (0 1 0); // 升力方向 dragDir (1 0 0); // 阻力方向 pitchAxis (0 0 1); // 俯仰轴 magUInf 1; // 来流速度大小 lRef 0.1; // 参考长度 Aref 0.01; // 参考面积 } }参数说明CofR是力矩的参考点取不同位置力矩值完全不同报告结果时必须写清楚取在哪。rhoInf对不可压算例就是常数密度量纲要和p的量纲设定一致否则系数会差一个量级。lRef和Aref决定了系数的绝对值写论文或做对比时必须在同一套参考量下比较才有意义。输出规律值得提前知道结果落在postProcessing/forces1/0/force.dat0这个子目录是 function object 的实例编号同一个算例里同名对象跑第二次会生成1/不会覆盖上一次的结果。这算是个好消息改参数重跑不用怕丢历史数据。找官方写法最快的办法不是翻文档是在算例库里反查# 在全部官方算例的 controlDict 里搜哪个用了 forceCoeffs find $FOAM_TUTORIALS -name controlDict | xargs grep -l forceCoeffs # 顺手看看它周边是怎么配的比凭空猜 key 名靠谱 find $FOAM_TUTORIALS -name controlDict | xargs grep -A 20 forceCoeffs参数说明xargs是把前一条命令的输出变成后一条命令的参数列表文件多的时候效率比-exec高grep -l只输出文件名不输出内容适合先定位再细看-A 20表示匹配行之后再打印 20 行上下文。这套组合在 OpenFOAM 里通用想找任何字典项的正确写法都可以照搬。5. 避坑与排查五个翻车现场的现象、原因与处置前面几章讲的是「应该怎么配」这一章讲「配错了长什么样」。下面五条都是我自己撞过或者帮人排查过的按现象、原因、解决三段写遇到对应症状直接对号入座。5.1 paraFoam 打开只有网格线没有云图现象时刻文件夹明明有0.1/、0.2/ParaView 里只能看到方块轮廓颜色是灰的切到U也没有颜色变化。原因三种可能。一是读到的其实是0/时刻的常量场初始场全场均匀看起来就像没数据二是touch出来的.OpenFOAM文件放错了位置不在算例根目录ParaView 加载的是空壳三是controlDict里writeInterval设得比endTime还大一个时刻都没写出。解决先foamListTimes确认到底有哪些时刻再ls -la确认.OpenFOAM文件与constant/同级。如果确实没写出场文件把controlDict的writeInterval改成 1 或者更小的值重跑。实在懒得改foamToVTK -latestTime转一份 VTK用 ParaView 直接开。5.2 checkMesh 全 OK一算就发散现象checkMesh输出Mesh OK正交性、偏斜度都在阈值内但icoFoam跑十几步以后残差直线上升终端刷出bounding警告。原因多数不是网格的锅是时间步和初始场。blockMeshDict里用了很猛的simpleGrading比如某个方向给到 20单元尺寸跨度太大最小单元那边库朗数爆掉或者deltaT是照最大网格尺寸估的忽略了壁面附近的加密还有一种容易被忽略的情况是初始场给了全零速度、但压力边界类型配错第一步就出现非物理的压力梯度。解决先把deltaT砍到原来的十分之一跑二十步看还炸不炸炸就继续砍这条能最快区分是时间步问题还是别的问题。同时打开自适应步长controlDict里设adjustTimeStep yes和maxCo 0.5让求解器自己压步长。如果压了还炸回去看simpleGrading把它改成 5 以内再试。5.3 速度残差降下去了continuity 卡在高位不动现象Ux、Uy的初始残差已经降到 1e-5continuity一直在 1e-2 附近横盘怎么跑都不降。原因压力方程没有钉住参考点或者参考点选在了流动剧烈的位置fvSolution里p的relTol设得太松比如 0.5内层根本没解到位nCorrectors只给了 1压力速度耦合不充分。解决确认PISO块里有pRefCell 0和pRefValue 0并且 0 号单元不在你关心的区域把p的relTol收到 0.05 或 0.01nCorrectors加到 2 或 3。改完看日志里每次压力迭代的 initial residual 是不是在稳步下降如果第一次就几乎不动那说明是边界条件或者源项的问题不是求解器设置。5.4 refineMesh 一跑整个域都被加密了现象本来只想加密中间一小块结果单元数从几百变成几千全算例的网格尺寸都变了。原因refineMesh在没读到refineMeshDict或者cells列表为空时默认行为是对全部网格加密。而cells为空的常见原因是topoSetDict里的name和refineMeshDict里的cells拼写不一致或者topoSet压根没跑成功constant/polyMesh/sets/下没有对应的 cellSet 文件。解决跑完topoSet之后先ls constant/polyMesh/sets/看文件在不在、名字对不对再打开文件确认单元数量是否合理。确认无误再refineMesh -overwrite。每次加密前备份polyMesh改错了直接覆盖回来比重建快得多。5.5 function object 写进去了postProcessing 里却是空的现象controlDict里加了fieldMinMax求解正常结束postProcessing/下没有对应目录或者目录在但文件是空的。原因写得比较杂。常见的是本文还有配套的精品资源点击获取