解验证(Solution Verification)
理论:数值解的三种误差
概述
加密网格求收敛阶,本应二阶却出现一阶甚至负值。是格式有问题吗?
先别怀疑格式,先怀疑迭代收敛。数值解的误差除了网格造成的离散误差,还有中途截断迭代造成的迭代误差和有限位数造成的舍入误差。加密网格离散误差变小,但收敛判据不变的话迭代误差不会变小,有时反而变大。迭代误差与离散误差相当时,表观阶数就会乱。解验证中要把三者分开,只估计离散误差。
误差分解
用网格比较估计离散误差,前提是迭代误差和舍入误差足够小。
算例问题
用二阶中心差分求解,由网格间距减半时的误差比求表观阶数 $p_{obs}$。计算正确时应接近2。
区分“验证”与“确认”
直到20世纪90年代,讨论计算可信度时常把计算是否正确求解方程(验证)与方程是否正确描述现实(确认)混为一谈。Roache在1998年的书中明确区分了两者,又把验证分为确认程序正确性的“代码验证”和估计单个计算误差的“解验证”。这一框架后来成为ASME V&V标准的骨架。不先通过解验证把握数值误差,与实验比较时看到的差异就无法分清是模型造成还是数值造成的。
算例
例1:迭代收敛判据的影响
用Gauss-Seidel法改变停止条件(残差降到初值的多少分之一),求网格加密时的最大误差和表观阶数:
| 收敛判据 | 10分 | 20分(阶数) | 40分(阶数) | 80分(阶数) |
|---|---|---|---|---|
| 10⁻³ | 7.3×10⁻³ | 1.1×10⁻³ (2.77) | 4.8×10⁻⁴ (1.16) | 8.7×10⁻⁴ (−0.85) |
| 10⁻⁶ | 8.3×10⁻³ | 2.1×10⁻³ (2.01) | 5.1×10⁻⁴ (2.00) | 1.3×10⁻⁴ (2.01) |
| 10⁻¹⁰ | 8.3×10⁻³ | 2.1×10⁻³ (2.01) | 5.1×10⁻⁴ (2.00) | 1.3×10⁻⁴ (2.00) |
80分收敛到10⁻⁶约需9,000次迭代,到10⁻¹⁰约需15,000次。网格越细,达到同样判据所需迭代越多。
例2:单精度舍入误差
| 分段数 | 双精度误差 | 单精度误差 |
|---|---|---|
| 40 | 5.1×10⁻⁴ | 5.1×10⁻⁴ |
| 160 | 3.2×10⁻⁵ | 3.7×10⁻⁵ |
| 640 | 2.0×10⁻⁶ | 1.5×10⁻⁴ |
| 2,560 | 1.3×10⁻⁷ | 3.6×10⁻³ |
| 10,240 | 7.9×10⁻⁹ | 0.45 |
单精度时,网格越细误差越大!
加密网格会使差分公式中相近值相减的次数增多,每次都损失有效位数。单精度只有约7位有效数字,超过某一细度后舍入误差就超过离散误差。双精度约有16位,本问题中到细得多的网格都没问题。实际的CFD和结构计算以双精度为基本,但在GPU上为速度用单精度时要注意。加密网格结果却没变好甚至变差时,要怀疑舍入误差。
解验证步骤
- 同时用残差和关心量(阻力、温度等)的变化确认收敛。
- 把收敛判据收紧一个数量级确认结果不变,估计迭代误差。
- 用三级以上网格和GCI等估计离散误差。
- 非稳态时也同样改变时间步长确认。
- 用双精度计算,确认舍入误差没有影响。
“网格越细结果越差”
某热流体计算研究网格依赖性,到中等网格结果都趋于稳定,最细网格却突然偏离。最细网格没有增加迭代次数,在同样时间就停止了计算,残差下降不够。继续迭代使残差再降两个数量级后,最细网格的结果也归队了。研究网格依赖性的铁则是:先确认每套网格迭代充分收敛再比较。
常见错误
错误与对策
| 错误 | 后果 | 对策 |
|---|---|---|
| 各网格迭代次数相同 | 细网格未收敛 | 按残差判断 |
| 只看残差 | 关心量未稳定 | 也监控关心量 |
| 单精度用细网格 | 舍入误差使结果变差 | 双精度 |
| 只用两套网格判断 | 无法确认阶数 | 三级以上 |
| 时间步长固定不变 | 残留时间方向误差 | 也改变时间步长 |
我想了解相关内容。
可以用Richardson外推工具试算阶数。相关页面参考Roache的GCI、三网格GCI、代码验证、构造解方法和ASME V&V 20。