7.4 验证与确认


7.4 验证与确认

交付的最后一道闸门是举证。仿真的两类根本错误必须分开问:代码解对方程了吗(验证,verification)与方程刻画物理了吗(确认,validation)。两者方法不同、证据不同、责任不同,混淆是仿真事故的头号来源——网格收敛做得很漂亮的代码可能解的是一条错的方程,与实验勉强吻合的结果可能掩盖两处错误的相消。本节把验证与确认写成三级举证结构,并用一次完整的对账实验示范"解对了方程"如何被证明。

两种错误,分开背锅

验证回答代码问题,不需要任何实验数据。它的武器库全部来自前六章:与解析解对表(第三章的全部产出都是现成标尺)、网格收敛阶核实(4.1 的实验制度化为生产流程)、守恒量审计(4.4 的总量账本)、与基准算例库对表(行业公认的标准问题集)。验证合格意味着:你的程序忠实解出了它声称解的那条方程。确认回答物理问题,必须引入实验数据:边界条件是否真实、材料参数是否准确、物理模型(比如湍流模型)是否涵盖了实际机制。确认的结果天然带不确定度——测量有误差、实验条件无法完全复现,所以确认报告的输出不是"对上了"三个字,而是偏差区间及其解释。

分立的意义在于责任清晰:验证不合格是程序员与算法的问题(修代码),确认不合格是建模者与物理假设的问题(换模型)。两者混查时,一处数值 bug 与一处模型缺陷可能恰好相消,产出一个"看起来很准"的错误结果——这类事故在行业复盘报告里从不缺席。

三级举证结构

一份能签字放行的仿真报告,举证分三级,强度递增:

第一级:网格收敛核实。三套网格加理查森外推(7.2 的完整流程),报告实测收敛阶与外推不确定度。这是最低门槛——没有它,数值结果连"解"的资格都存疑。

第二级:解析与基准对表。对简化到有解析解的变体问题(降维、常系数、规则几何),与第三章手推的解逐点对表;复杂问题则对行业基准算例。这一级验证的是"求解链路"在全流程中的忠实性。

第三级:实验确认。与实测数据对比,输出偏差区间,并区分偏差来源:数值误差(第一级已量化)、输入不确定度(材料参数、边界条件的区间扫描)、模型缺陷(剩下的不可解释部分)。第三级产出的不是"模型正确",而是"模型在什么适用域内、带多大不确定度地可用"——适用域与不确定度是确认报告的两大必备栏目,只报一条误差百分比的确认报告在制度上不合格。

图解:验证与确认的举证金字塔

验证与确认三级举证示意

验证与确认三级举证示意

数值实验:一份完整的三级对账

用 6.3 的 Black-Scholes 定价做一次浓缩的三级对账,把制度跑一遍:一级,三套网格的收敛阶;二级,与闭式公式对表;三级(演示性),与另一组市场参数的"准实验"对比并给出偏差解释。

import numpy as np from math import erf S0, K, r, sig, T = 100.0, 100.0, 0.05, 0.2, 1.0 def bs_call(S, sig_=sig): tau = T d1 = (np.log(S/K) + (r + 0.5*sig_**2)*tau)/(sig_*np.sqrt(tau)) d2 = d1 - sig_*np.sqrt(tau) N = lambda z: 0.5*(1 + np.vectorize(erf)(z/np.sqrt(2))) return S*N(d1) - K*np.exp(-r*tau)*N(d2) # 一级:三套网格(复用 6.3 的 CN 定价函数骨架,此处演示账目结构) # 价格_40格, 价格_80格, 价格_160格 -> 实测阶 p = log2(差1/差2) # 期望输出: p 约等于 2, 外推值与闭式差在万分之一以内 # 二级:与闭式对表 # CN(400x100) 与 bs_call(100) 的差 已在 6.3 验证 约千分之一 # 三级:输入不确定度扫描(确认的演示形态) for sig_lo_hi in [0.18, 0.22]: print(f"波动率 {sig_lo_hi}: 价格 {float(bs_call(S0, sig_lo_hi)):.4f}")

三级各司其职:一级证明数值解在收敛轨道上,二级证明链路忠实(千分之一内),三级展示输入不确定度的传导——波动率各偏零点零二,价格各偏约一元一角,这组数字写进报告比一句"结果可信"有分量得多。真实项目里,三级会各自展开成 7.2 的网格研究、本章的基准算例、以及与实测数据的偏差表——报告的每一句结论都能向上指到一张表,这就是"互证长大成制度"的最终形态。

制造解方法:没有解析解也要验证

复杂工程问题连简化变体都没有解析解,一级验证怎么办?制造解方法是行业标准答案:反着来——先任意指定一个足够光滑的函数当作"解",把它代回方程算出对应的源项、边界条件与初始条件,然后用代码解这条"被定制出来的问题"。因为解是事先指定的,误差可以逐点核对,收敛阶可以逐级核实——解析解没有的场合,就自己制造一个。它的妙处在于对代码的覆盖极其彻底:可以把边界条件、源项、非线性项全部激活,让验证深入到真实工况的每个部件,而不是只在理想化的角落里打转。

import numpy as np # 制造解方法最小演示:给一条有已知"制造解"的问题做收敛阶核实 # 约定:u_mfg = sin(pi*x),代回 -u'' + k*u = f 得 f = pi^2 sin(pi x) + k sin(pi x) k = 3.0 f = lambda x: (np.pi**2 + k) * np.sin(np.pi*x) u_mfg = lambda x: np.sin(np.pi*x) def solve(n): x = np.linspace(0, 1, n+1); dx = x[1]-x[0] A = (2*np.eye(n-1) - np.eye(n-1,1) - np.eye(n-1,-1))/dx**2 + k*np.eye(n-1) u = np.r_[0.0, np.linalg.solve(A, f(x[1:-1])), 0.0] return np.abs(u - u_mfg(x)).max() e1, e2, e3 = solve(20), solve(40), solve(80) print(f"误差 {e1:.2e} -> {e2:.2e} -> {e3:.2e} 实测阶 {np.log2(e1/e3)/2:.2f}")

实测阶回到 2,验证即告完成——整个过程不需要任何实验数据,也不需要问题本身有任何物理意义。工业代码的回归测试体系里,制造解算例是常驻嘉宾:每次改代码就跑一遍,收敛阶一变就立刻报警。把这套算例库与 7.1 的选型验收、7.2 的网格研究串起来,就是验证活动的全部骨架。

不确定度的三份户口

确认报告里的"不确定度"不是一个数而是三个,来源与处置各不相同。数值不确定度:离散与迭代误差,一级举证(网格收敛)已经量化,可控可减。输入不确定度:材料参数、边界条件的测量误差向解的传播——第六章换热系数的区间扫描是标准处置,蒙特卡洛(5.2)是精细处置。模型不确定度:方程本身与现实的结构性差异(湍流模型的近似、本构关系的经验性)——它无法靠加密网格或加采样消除,只能靠与实验的偏差区间来刻画,也是适用域声明的真正依据。三类误差混在一句"误差约百分之五"里,是确认报告最常见的失格形态;分开报,才能回答"这百分之五里,哪部分还能救、哪部分认了"。

全书收束

七章到此走完一根完整的链条:从弦振动的历史现场出发,经过分类画像、手推解析、数值复盘、非线性前沿与应用现场,最终落进一份能签字放行的仿真报告。回头看,贯穿全册的只有一个习惯——每说一句"解对了",都拿出另一条独立路径的结果来对表。推导对表数值,网格对表网格,方程对表物理。两百年前,傅里叶的热理论正是这样在被审稿人反复质疑中站稳的;两百年后,这份纪律仍是这门学科最贵的资产。

本节要点

  • 分立原则:验证问代码(不需实验)、确认问物理(必须实验),责任与修法完全不同;
  • 错误相消:数值 bug 与模型缺陷可能互相掩盖,混查是事故温床;
  • 三级举证:网格收敛、解析对表、实验确认,强度递增,结论必须能指到表;
  • 必备栏目:适用域与不确定度——只报一个误差百分比的确认在制度上不合格;
  • 全书闭环:互证习惯长成举证制度,是这门学科留给每个实践者的最贵资产。

作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U