MMS:二维定常热传导——故障排查指南
更详尽的内容请访问 mms-heat-2d.html。
作为"第一题"的二维定常热传导MMS
定常热传导的MMS是代码验证入门的最佳题目。理由是源项可以手算——例如在单位正方形区域上取导热系数 \( k \) 为常数,制造解取 \( T_m = \sin(\pi x)\sin(\pi y) \),则
$$ s = -k\,\nabla^2 T_m = 2\pi^2 k \,\sin(\pi x)\sin(\pi y) $$
一行就出来了。边界可以全周取 \( T_m = 0 \)(Dirichlet),连符号计算都不需要。在这道"能把答案对到底"的题上先掌握验证的套路(网格序列、误差范数、观测精度阶),再走向弹性与流体,是最短的学习路径。话虽如此,这么简单的问题也有好几处会卡住,本页按症状逐一化解。
五步标准流程
- 把源项 \( s(x,y) \) 作为体积热源(单位W/m³:与 \( k \) 的单位保持一致)定义到求解器中
- 全周施加Dirichlet边界 \( T = 0 \)(一般情形是 \( T_m \) 的边界值)
- 在三个网格级别(例如10×10、20×20、40×40)上求解
- 在各级别计算误差范数 \( E_h = \|T_h - T_m\|_{L^2} \)
- 把观测精度阶 \( p = \ln(E_{2h}/E_h)/\ln 2 \) 与单元的理论精度阶(一次单元为2,二次单元为3——按 \( L^2 \) 范数)作比较
症状1:误差一直下不去、明显是另一个解
| 检查项 | 内容 |
|---|---|
| 源项的符号 | 符号约定随方程的写法而变(是 \( -\nabla\cdot(k\nabla T) = s \) 还是 \( \nabla\cdot(k\nabla T) + s = 0 \))。符号反了解就会上下翻转——看一眼温度云图便一目了然 |
| 漏掉系数 | 把 \( 2\pi^2 k \) 里的 \( k \) 丢掉,解的形状不变而幅值差 \( 1/k \) 倍。"形状对、幅值不对"就是这一类 |
| 漏给边界 | 有限元中未指定的边会自动变成绝热(零Neumann)。哪怕漏掉一条边,解也会大变。用可视化确认边界的分配 |
| 单位制 | 在毫米制模型里按W/m³加源项会差10⁹倍。与手算的量级作对比 |
症状2:能收敛,但精度阶达不到理论值
- 源项空间分布的给法——若工具的体积热源只能按"区域常数"给定,就成了逐单元的常数近似,精度被限制在一阶。要用坐标相关的表达式、用户函数或(足够细的)表格插值来给
- 误差的测法——精确解与数值解是否在同一位置取值,\( L^2 \) 是否加了体积权重(详见精度阶计算的故障排查)
- 混入Neumann边的情形——热流密度 \( q = -k\,\partial T_m/\partial n \) 的符号(外向为正还是流入为正:以工具的约定为准),以及沿边变化的值的积分精度
- 二次单元上误差变成"零"——多项式(二次及以下)的制造解会被二次单元精确重现,因而测不出精度阶。要用三角函数系(本页的 \( T_m \) 没有这个问题)
症状3:改成温度相关的 k(T) 后就对不上了
入门之后的下一步是引入 \( k(T) \),此时最容易漏掉的是源项的推导会随之改变。正确的是
$$ s = -\nabla\cdot\left(k(T_m)\,\nabla T_m\right) = -k(T_m)\nabla^2 T_m - k'(T_m)\,|\nabla T_m|^2 $$
而漏掉第二项(\( k' \) 项)是定番错误。从这一步起改用符号推导(SymPy等)更稳妥。另外由于问题已变成非线性,要把迭代(Picard/Newton)的收敛压到比离散化误差低两个数量级——收敛不深的非线性计算,会轻易毁掉线性时本已出得来的精度阶。
症状4:网格加细后误差不再下降
你多半会在这道简单题上第一次体验"误差地板"。成因有:①线性求解器的收敛判据(迭代法的情形);②舍入误差(误差已到 \( 10^{-10} \) 量级时);③源项与边界值评估中混入的近似(表格插值过粗等)。诊断有两招:看误差的绝对值,以及把收敛判据收紧一个数量级看变化。做到"一直加密到撞上地板,再查明地板的成因并写进报告",验证报告的完成度就上了一个台阶。
症状5:商用工具里加不进坐标相关的源项
MMS能否实施,与其说取决于求解器本身,不如说取决于"能不能定义坐标相关的体积热源"。主要工具的路径是:Ansys Mechanical=函数定义(Function/APDL的%table%与坐标函数);Abaqus=解析场(Analytical Field)或DFLUX子程序;COMSOL=直接键入表达式(最省事);OpenFOAM=codedSource/fvOptions;Fluent=UDF(DEFINE_SOURCE)。即便是无法从图形界面输入表达式的工具,也可以用足够细的空间表格+插值代替(细到插值误差不会污染精度阶——参见症状2)。把"自己这套工具里的MMS实施路径"确立一次,以后各类验证都能反复复用。
检查清单与进阶
- 是否把源项的符号约定、系数与单位同求解器的方程写法核对过
- 是否用可视化确认了全部边界的分配(注意未指定=绝热)
- 是否确认了误差范数的测法(同位置取值、体积权重)
- 是否在三级以上网格上算了观测精度阶并与理论精度阶作比较
- 是否查明了误差地板的成因(收敛判据/舍入)
- 进阶:是否逐级扩展到了混入Neumann/Robin边界的版本、k(T)非线性版本、非定常版本(时间精度阶的分离测量)
老实说,我一直觉得专门去做这么简单的题有什么意义……
这道题真正的产出不是"解出来了",而是把验证的全套流程走通一遍的经验,以及一套可复用的脚本。网格序列怎么造、误差范数怎么算、精度阶怎么画图、地板怎么判别——这里做出来的工具,到弹性、到NS都能原样搬过去。而且问题足够简单,流程的bug不会和物理的bug搅在一起。这就像练音阶:在简单的练习上把"型"打好,难曲子才弹得下来。作为一天就能完成的投入,它是代码验证领域回报率最高的一道题。
相关文章:MMS概要(整合版)、收敛精度阶的故障排查、二维弹性MMS(下一步)。
帮助
更多
错误