← 首页← Home

一维黏性 Burgers 方程的离散伴随:格点格式

Discrete adjoints for one-dimensional viscous Burgers: node-centred scheme

算例与格心页相同:区间 [0,1][0,1] 上带源项的一维定常黏性 Burgers 方程,两端给定值,固定正黏性 ν\nu;不同的是未知量放在网格节点上,每个节点周围是它的对偶控制体,两端的行是边界约束。本页先介绍方程、它的作用和网格,再从一个面上的通量出发,依次写出残差、前向(tangent)与伴随(adjoint),最后用它们计算振幅 aa、相位 φ\varphi 和黏性 ν\nu 的灵敏度,并与复数步长、完整重算差分、独立的 Python 大网格实测和连续伴随对照;同一问题的格心格式见格心页,两种格式的差别在页中处处量出。解有精确公式,所以每个导数都能和真值比较。

The test case is that of the cell-centred page: the steady one-dimensional viscous Burgers equation with a source on [0,1][0,1], a prescribed value at each end and a fixed positive viscosity ν\nu. What differs is where the unknowns live: at the mesh nodes, with the dual intervals around them as control volumes and the two end rows replaced by the boundary constraints. After introducing the equation, what it is for and the mesh, this page starts with the flux on one face and builds the residual, the forward (tangent) and the adjoint, then uses them to compute the sensitivities to the amplitude aa, the phase φ\varphi and the viscosity ν\nu, and checks them against complex step, finite differences with full re-solves, independent large-grid Python runs and the continuous adjoint; the same problem with cell-centred unknowns is on the cell-centred page, and the pages measure where the two schemes differ. The solution has a closed form, so every derivative can be compared with the truth.

全页路线图:从设计输入到梯度设计输入 DD = (a, φ, ν)3 个分量第 12 节求解R(U, D) = 0Newton,带状 LU第 5、6 节状态 U9 个未知量每个节点 1 个第 2 节目标 Jh线性泛函 Jhg = (∂Jh/∂U)T第 7 节梯度 dJh/dD3 个分量第 12 节前向(tangent)路线:从左往右,每个设计分量一次D˙ = ek第 k 个设计分量Av = −RD D˙​一次线性求解v = U˙​状态的切向量J˙h = gTv方向导数dJh/dDk梯度的一个分量3 个设计分量 → 3 次线性求解,每次得到梯度的一个分量(第 8、10 节)伴随(adjoint)路线:从右往左,只解一次dJh/dD = ψTRD全部 3 个分量ψ伴随变量ATψ = −g一次转置求解g = (∂Jh/∂U)T目标对状态的导数1 次转置求解,再做乘积 ψTRD(不再求解),得到全部 3 个分量(第 9、11、12 节)代价:3 个设计分量 ⇒ 前向 3 次线性求解,伴随 1 次全页路线图:从设计输入到梯度原始计算前向 ×3伴随 ×1从上往下从下往上设计输入 DD = (a, φ, ν)第 12 节求解R(U, D) = 0第 5、6 节状态 U9 个未知量第 2 节目标 Jhg = (∂Jh/∂U)T第 7 节梯度 dJh/dD3 个分量第 12 节D˙ = ek第 k 个设计分量Av = −RD D˙​一次线性求解v = U˙​状态的切向量J˙h = gTv方向导数dJh/dDk梯度的一个分量dJh/dD = ψTRD全部 3 个分量ψ伴随变量ATψ = −g一次转置求解g = (∂Jh/∂U)T目标对状态的导数3 个设计分量:前向 3 次线性求解,伴随 1 次
Page roadmap: from the design input to the gradientdesign input DD = (a, φ, ν)3 componentsSection 12solveR(U, D) = 0Newton withbanded LUSections 5–6state U9 unknownsone per nodeSection 2objective Jhlinear functional Jhg = (∂Jh/∂U)TSection 7gradient dJh/dD3 componentsSection 12Tangent (forward) route: left to right, once per design componentD˙ = ekdesign component kAv = −RD D˙​one linear solvev = U˙​tangent of the stateJ˙h = gTvdirectional derivativedJh/dDkone gradient component3 design components → 3 linear solves, each giving one gradient component (Sections 8 and 10)Adjoint route: right to left, a single solvedJh/dD = ψTRDall 3 componentsψadjoint variableATψ = −gone transposed solveg = (∂Jh/∂U)Tobjective vs state1 transposed solve, then the product ψTRD (no further solve) gives all 3 components (Sections 9, 11 and 12)Cost: 3 design components ⇒ 3 tangent solves against 1 adjoint solvePage roadmap: from the design input to the gradientPrimalTangent ×3Adjoint ×1top to bottombottom to topdesign input DD = (a, φ, ν)Section 12solveR(U, D) = 0Sections 5–6state U9 unknownsSection 2objective Jhg = (∂Jh/∂U)TSection 7gradient dJh/dD3 componentsSection 12D˙ = ekcomponent kAv = −RD D˙​one linear solvev = U˙​state tangentJ˙h = gTvalong component kdJh/dDkone componentdJh/dD = ψTRDall 3 componentsψadjoint variableATψ = −gtransposed solveg = (∂Jh/∂U)Tobjective vs state3 design components:3 tangent solves, 1 adjoint solve
全页路线图 · 从设计输入到梯度。上排是原始计算:由设计输入求解离散方程,得到状态,再算出目标。前向(tangent)路线顺着计算方向,每个设计分量解一次线性方程,得到梯度的一个分量;伴随(adjoint)路线逆着计算方向,只解一次转置方程,再做一次乘积就得到全部分量。本页默认设置下有 3 个设计分量:3 次前向求解对 1 次伴随求解。方框下方的节号可以点击。Page roadmap · From the design input to the gradient. The top row is the primal computation: solve the discrete equations for the design input, obtain the state, then evaluate the objective. The tangent (forward) route follows the direction of computation and solves one linear system per design component, each giving one gradient component; the adjoint route runs against it, solves a single transposed system and obtains every component with one more product. With this page's default settings there are 3 design components: 3 tangent solves against one adjoint solve. The section numbers under the boxes are links.
本页用到的词Words used on this page
自动微分(AD)automatic differentiation (AD)
把程序逐语句用链式法则求导。前向模式(tangent)把一个输入方向推过程序;反向模式(adjoint)把一个输出权重拉回程序。differentiating a program statement by statement with the chain rule. Forward mode (tangent) pushes one input direction through the program; reverse mode (adjoint) pulls one output weight back through it.
原始(primal)primal
求导之前的原始计算。the original computation, before differentiation.
残差与 Jacobianresidual and Jacobians
R(𝐔,D)=0R(\mathbf U,D)=0 是离散方程;A=∂R/∂𝐔A=\partial R/\partial\mathbf U 与 RD=∂R/∂DR_D=\partial R/\partial D 是它对状态和对设计的 Jacobian。R(𝐔,D)=0R(\mathbf U,D)=0 are the discrete equations; A=∂R/∂𝐔A=\partial R/\partial\mathbf U and RD=∂R/∂DR_D=\partial R/\partial D are its Jacobians with respect to the state and the design.
构造解manufactured solution
先选解,再算出使它精确成立的源项,于是每个导数都有已知的真值。choose the solution first and compute the source that makes it exact, so that every derivative has a known true value.
对偶控制体(对偶区间)dual volume (dual interval)
节点周围的控制体:内部节点的对偶区间从它与左邻节点的中点伸到它与右邻节点的中点,宽 hh;两端节点的只有半宽 h/2h/2。内部节点的残差行就是这个区间上的守恒平衡。the control volume around a node: for an interior node it runs from the midpoint to its left neighbour to the midpoint to its right neighbour, width hh; at the two end nodes it has half the width, h/2h/2. The row of an interior node is the conservation balance on this interval.
重构与迹reconstruction and traces
重构由节点值构造面上的值:常数(一阶)或带斜率(二阶);迹是由一侧节点重构出的面上的值(qLq_L 来自左侧,qRq_R 来自右侧)。reconstruction builds face values from nodal values: constant (first order) or with a slope (second order); a trace is the value at a face reconstructed from the node on one side (qLq_L from the left, qRq_R from the right).
Rusanov 通量Rusanov flux
一种数值通量:取两侧物理通量的平均,再减去与跳跃成正比的耗散。a numerical flux that averages the physical fluxes of the two sides and subtracts a dissipation proportional to the jump.
网格 Péclet 数mesh Péclet number
uh/νu h/\nu:一个网格间距上对流与扩散之比。uh/νu h/\nu: the ratio of convection to diffusion over one mesh interval.
LU、GS、GMRESLU, GS, GMRES
LU 把矩阵分解为下三角与上三角因子(这里是带状 LU);GS 是 Gauss–Seidel 迭代,逐个求解未知量,并立即使用其余未知量的最新值;GMRES 是广义最小残差法,一种只需矩阵–向量乘积的 Krylov 求解器。LU factorises a matrix into lower- and upper-triangular factors (banded LU here); GS is the Gauss–Seidel iteration, which solves for one unknown at a time with the newest values of the others; GMRES is the generalised minimal residual method, a Krylov solver that needs only matrix–vector products.
有限差分(FD)与复数步长finite differences (FD) and the complex step
有限差分由重新求解的结果的差商得到导数;复数步长取 f(x+iτ)/τf(x+\mathrm i\tau)/\tau 的虚部作导数:不做相减,没有舍入相消。finite differences take the derivative from a difference quotient of re-solved results; the complex step takes the imaginary part of f(x+iτ)/τf(x+\mathrm i\tau)/\tau: no subtraction, no cancellation.
点积检验dot test
检验伴随代码是前向代码的转置:两个内积必须在舍入误差内相等。checks that the adjoint code is the transpose of the tangent code: the two inner products must agree to rounding.
CFDCFD
计算流体力学。computational fluid dynamics.

第 1 节Section 1

方程:一维定常黏性 Burgers

The equation: steady one-dimensional viscous Burgers

本节实验:读图 1 的下图,扩散通量比对流通量小多少?再读图 2:同一个 u∗u^* 在不同 ν\nu 下需要什么样的源项?

Experiment: In the lower panel of Figure 1, how much smaller is the diffusive flux than the convective one? Then read Figure 2: what source does the same u∗u^* need at different ν\nu?

本节的内容与离散格式无关:方程、构造解、设计和目标对格心页(adjoint_burgers_viscous_cell.html)同样成立,两页解的是同一个问题。区别只在未知量放在哪里:那里在单元中心,本页在网格节点上(第 2 节)。两种格式给出不同数值之处,各节会指出并量出来。

Nothing in this section depends on the discretisation: the equation, the manufactured solution, the design and the objective are those of the cell-centred page (adjoint_burgers_viscous_cell.html), which solves the same problem. The two pages differ only in where the unknowns live: at the cell centres there, at the mesh nodes here (Section 2). Where the two schemes give different numbers, the sections say so and measure it.

从守恒律到定常方程

From a conservation law to the steady equation

黏性 Burgers 方程在其他一维页面的 Burgers 方程上增加了分子扩散。量 u(x,t)u(x,t) 沿 xx 以自身的值为速度被输运,同时按系数 ν>0\nu>0 扩散;写成守恒形式,总通量有两部分——对流通量 u2/2u^2/2 与扩散通量 −νux-\nu u_x——区间内还有源项 s(x)s(x):

The viscous Burgers equation adds molecular diffusion to the Burgers equation of the other one-dimensional pages. A quantity u(x,t)u(x,t) is carried along xx with its own value as the speed and spreads by diffusion with the coefficient ν>0\nu>0. In conservation form the total flux has two parts, the convective flux u2/2u^2/2 and the diffusive flux −νux-\nu u_x, and a source s(x)s(x) acts inside the interval:

ut+(12u2−νux)x=s(x).u_t+\Bigl(\tfrac12u^2-\nu u_x\Bigr)_x=s(x).

本页只研究固定正黏性下的定常解。令 ut=0u_t=0,并记总通量为 q(u,ux)=12u2−νuxq(u,u_x)=\tfrac12u^2-\nu u_x,得到要离散的方程;因为含二阶导数,两端各需要一个给定值(无黏 Burgers 页面只给入口条件,不需要出口条件):

This page studies steady solutions at a fixed positive viscosity. Setting ut=0u_t=0 and writing q(u,ux)=12u2−νuxq(u,u_x)=\tfrac12u^2-\nu u_x for the total flux gives the equation to be discretised. Because it contains a second derivative it needs a prescribed value at each end (the inviscid Burgers pages, with an inlet condition only, needed none at the outlet):

qx=(12u2−νux)x=u ux−ν uxx=s(x),x∈(0,1),u(0)=uin,u(1)=uout.q_x=\Bigl(\tfrac12u^2-\nu u_x\Bigr)_x=u\,u_x-\nu\,u_{xx}=s(x),\qquad x\in(0,1),\qquad u(0)=u_{\rm in},\quad u(1)=u_{\rm out}.

ν>0\nu>0 使解光滑:陡变被扩散成薄层,层宽与 ν\nu 除以速度(或速度差)同量级。构造解本身没有层。u>0u>0 时这个问题的边界层只能出现在出口 x=1x=1(默认设计下层宽 ν/uout=0.011\nu/u_{\rm out}=0.011),入口 x=0x=0 处的层属于伴随 λ\lambda(图 4,第 11、16 节与附录 A)。网格 Péclet 数 Peh=u h/ν\mathrm{Pe}_h=u\,h/\nu 就是网格间距与这个层宽 ν/u\nu/u 之比:Peh<1\mathrm{Pe}_h<1 表示一个网格间距比层还窄(第 3 节把它与格式的人工黏性联系起来)。激波属于一维无黏 Burgers 页(格点页与它的格心页)的附录 B,ν→0\nu\to0 与 h→0h\to0 的极限顺序见它的附录 D(D.4);本页的 ν\nu 始终固定。

With ν>0\nu>0 the solution is smooth: a steep change is spread into a thin layer whose width is of the order of ν\nu divided by the speed (or the speed jump). The manufactured solution has no layer. With u>0u>0 a boundary layer of this problem can only sit at the outlet end x=1x=1 (width ν/uout=0.011\nu/u_{\rm out}=0.011 at the default design), while the layer at the inlet end x=0x=0 belongs to the adjoint λ\lambda (Figure 4; Sections 11 and 16 and Appendix A). The mesh Péclet number Peh=u h/ν\mathrm{Pe}_h=u\,h/\nu is the mesh spacing in units of that layer width ν/u\nu/u: Peh<1\mathrm{Pe}_h<1 means that one interval is narrower than the layer (Section 3 relates it to the artificial viscosity of the scheme). Shocks belong to Appendix B of the inviscid one-dimensional Burgers page (the node-centred page and its cell-centred partner) and the orders of the limits ν→0\nu\to0, h→0h\to0 to its Appendix D (D.4); here ν\nu stays fixed.

一个构造解:先给解,再算源项

A manufactured solution: prescribe the solution, derive the source

要把每个导数都和精确答案比较,本页先规定解,再由解构造源项。取 u∗u^* 为在平均值 1 上叠加的正弦波,振幅为 aa,相位为 φ\varphi;u∗u^* 对每个设计都是精确解。把它代入方程,就得到源项和两端的给定值:

To compare every derivative with an exact answer, the page prescribes the solution first and builds the source from it. Take u∗u^* to be a sine wave on the mean 1, with amplitude aa and phase φ\varphi; it is the exact solution for every design. Inserting it into the equation defines the source and the two end values:

u∗(x)=1+a sin⁡z,z=2π(x−φ),q∗=12(u∗)2−νux∗,s(x)=qx∗=u∗ux∗−νuxx∗=2πa cos⁡z (1+a sin⁡z)+4π2νa sin⁡z,uin=u∗(0)=1−a sin⁡2πφ,uout=u∗(1)=uin.\begin{aligned}u^*(x)&=1+a\,\sin z,\qquad z=2\pi(x-\varphi),\qquad q^*=\tfrac12(u^*)^2-\nu u^*_x,\\ s(x)&=q^*_x=u^*u^*_x-\nu u^*_{xx}=2\pi a\,\cos z\,(1+a\,\sin z)+4\pi^2\nu a\,\sin z,\\ u_{\rm in}&=u^*(0)=1-a\,\sin 2\pi\varphi,\qquad u_{\rm out}=u^*(1)=u_{\rm in}.\end{aligned}

解不依赖 ν\nu,源项则依赖:其中 −νuxx∗=4π2νa sin⁡z-\nu u^*_{xx}=4\pi^2\nu a\,\sin z 这一项就是源项必须补上的扩散(图 2)。u∗u^* 以 1 为周期,所以两端的给定值相等;默认值下 uin=uout=0.9148u_{\rm in}=u_{\rm out}=0.9148。

The solution does not depend on ν\nu, but the source does: the term −νuxx∗=4π2νa sin⁡z-\nu u^*_{xx}=4\pi^2\nu a\,\sin z is the diffusion that the source has to supply (Figure 2). Because u∗u^* has period 1 the two end values are equal; at the defaults uin=uout=0.9148u_{\rm in}=u_{\rm out}=0.9148.

设计、目标和它们的精确导数

The design, the objective and their exact derivatives

设计输入是 D=(a,φ,ν)D=(a,\varphi,\nu),共 3 个分量。aa 与 φ\varphi 同时改变源项和两端的给定值;ν\nu 改变物理通量本身,同时也改变源项。目标是解的一个加权积分,权重 1+x1+x:

The design input is D=(a,φ,ν)D=(a,\varphi,\nu) with 3 components. Changing aa or φ\varphi changes the source and the two end values together; changing ν\nu changes the physical flux itself and, through −νuxx∗-\nu u^*_{xx}, the source. The objective is a weighted integral of the solution with the weight 1+x1+x:

J(u)=∫01(1+x) u(x) dx.J(u)=\int_0^1(1+x)\,u(x)\,\mathrm dx.

对构造解可以直接积分,目标和它的三个导数都有闭式(ν\nu 不出现,因为 u∗u^* 不依赖它):

For the manufactured solution the integral is exact, so the objective and its three derivatives have closed forms (ν\nu does not appear because u∗u^* does not depend on it):

J∗=32−a cos⁡2πφ2π,(∂J∗∂a, ∂J∗∂φ, ∂J∗∂ν)=(−cos⁡2πφ2π, a sin⁡2πφ, 0).J^*=\frac32-\frac{a\,\cos 2\pi\varphi}{2\pi},\qquad \Bigl(\frac{\partial J^*}{\partial a},\ \frac{\partial J^*}{\partial\varphi},\ \frac{\partial J^*}{\partial\nu}\Bigr)=\Bigl(-\frac{\cos 2\pi\varphi}{2\pi},\ a\,\sin 2\pi\varphi,\ 0\Bigr).

默认设计下 J∗=1.471198J^*=1.471198,梯度 (−0.144008, 0.085156, 0)(−0.144008,\ 0.085156,\ 0)。离散梯度随网格加密趋向的就是这些值(第 15 节的数据显示这一点;这是数值观察,不是证明)。有限网格上的离散目标 Jh(D)J_h(D) 是另一个函数(第 7 节;本页里它是作用在节点值上的梯形公式,第 2 节),切线和伴随算出的是它的梯度,不是这个精确梯度;两者的比较见第 10 至 12 节、第 15 节和第 16 节。

At the defaults J∗=1.471198J^*=1.471198 and the gradient is (−0.144008, 0.085156, 0)(−0.144008,\ 0.085156,\ 0). These are the values that the discrete gradients approach as the mesh is refined, as the data of Section 15 show (a numerical observation, not a proof). On a finite mesh the discrete objective Jh(D)J_h(D) is a different function (Section 7; on this page it is the trapezoid rule applied to the nodal values, Section 2), and what the tangent and the adjoint compute is its gradient, not this exact one; the two are compared in Sections 10 to 12, 15 and 16.

图 1 · 问题全貌(默认设计,N=8,无限制器线性重构)。上:构造解 u*(实线)、精确节点值 u*(x_j)(空心圆)、本页算出的离散解 U_j(实心点,每个节点一个);两端的方块是给定值 u_in=u_out=0.9148,两个端点处的节点恰好取这个值。下:总通量 q* 及其两部分;扩散通量 -ν u*_x 最大只有 0.0126,图中放大 20 倍。0.70.80.911.11.21.300.20.40.60.81xuuin​ = 0.9148uout​ = 0.9148精确解 u*精确节点值 u*(xj​)离散解 Uj​(N = 8)−0.200.20.40.60.800.20.40.60.81xq总通量 q* = u*²/2 − ν u*x​对流 u*²/2扩散 −ν u*x​(×20)
图 1 · 问题全貌(默认设计,N=8N=8,无限制器线性重构)。上:构造解 u∗u^*(实线)、精确节点值 u∗(xj)u^*(x_j)(空心圆)、本页算出的离散解 UjU_j(实心点,每个节点一个);两端的方块是给定值 uin=uout=0.9148u_{\rm in}=u_{\rm out}=0.9148,两个端点处的节点恰好取这个值。下:总通量 q∗q^* 及其两部分;扩散通量 −νux∗-\nu u^*_x 最大只有 0.0126,图中放大 20 倍。
Figure 1 · The problem at a glance (default design, N=8, unlimited linear reconstruction). Top: the manufactured solution u* (solid), its exact nodal values u*(x_j) (rings) and this page's discrete solution U_j (dots, one per node); the squares at the ends are the prescribed values u_in=u_out=0.9148, which the two end nodes carry exactly. Bottom: the total flux q* and its two parts; the diffusive flux -ν u*_x is at most 0.0126, drawn 20 times larger.0.70.80.911.11.21.300.20.40.60.81xuuin​ = 0.9148uout​ = 0.9148exact u*exact nodal values u*(xj​)discrete Uj​ (N = 8)−0.200.20.40.60.800.20.40.60.81xqtotal flux q* = u*²/2 − ν u*x​convective u*²/2diffusive −ν u*x​ (×20)
Figure 1 · The problem at a glance (default design, N=8N=8, unlimited linear reconstruction). Top: the manufactured solution u∗u^* (solid), its exact nodal values u∗(xj)u^*(x_j) (rings) and this page's discrete solution UjU_j (dots, one per node); the squares at the ends are the prescribed values uin=uout=0.9148u_{\rm in}=u_{\rm out}=0.9148, which the two end nodes carry exactly. Bottom: the total flux q∗q^* and its two parts; the diffusive flux −νux∗-\nu u^*_x is at most 0.0126, drawn 20 times larger.

图 1 的下图回答了实验的第一问:对流通量在 0.32 与 0.72 之间,扩散通量最大只有 0.0126,不超过对流通量的 4%。黏性几乎不改变解的通量,却决定了第 11、16 节里伴随场的结构;先记住这一点。上图里,每个节点一个点:8+1 个未知量中两端的两个恰好等于给定值,其余的点离空心圆的最远距离是 0.0278(N=8N=8 的粗网格;这个距离随网格加密怎样缩小,见第 15 节)。

The lower panel of Figure 1 answers the first question of the experiment: the convective flux lies between 0.32 and 0.72 and the diffusive flux is at most 0.0126, no more than 4% of it. Viscosity hardly changes the flux of the solution, yet it decides the structure of the adjoint field in Sections 11 and 16; keep that in mind. In the upper panel there is one dot per node: of the 8+1 unknowns the two at the ends equal the prescribed values exactly, and the other dots lie at most 0.0278 from their rings (a coarse mesh, N=8N=8; how this distance shrinks under refinement is measured in Section 15).

用页首的控件改变 NN、重构和设计,下面的面板马上给出离散解、精确节点值、每个节点上的误差,以及离散目标的误差由哪两部分组成:

Change NN, the reconstruction and the design with the controls at the top, and the panel below shows at once the discrete solution, the exact nodal values, the error at every node, and the two parts that the error of the discrete objective is made of:

图 2 · 同一个 u* 在不同黏性下需要的源项 s(x)。ν=0 时只有对流部分(虚线);扩散项 4π^2ν a sin z 的幅度与 ν 成正比:ν=0.01 时 0.079,ν=0.1 时 0.790。a=0.2,φ=0.07。−1.5−1−0.500.511.500.20.40.60.81xsν = 0(只有对流)ν = 0.01ν = 0.05ν = 0.1
图 2 · 同一个 u∗u^* 在不同黏性下需要的源项 s(x)s(x)。ν=0\nu=0 时只有对流部分(虚线);扩散项 4π2νa sin⁡z4\pi^2\nu a\,\sin z 的幅度与 ν\nu 成正比:ν=0.01\nu=0.01 时 0.079,ν=0.1\nu=0.1 时 0.790。a=0.2a=0.2,φ=0.07\varphi=0.07。
Figure 2 · The source s(x) that the same u* needs at different viscosities. For ν=0 only the convective part remains (dashed); the amplitude of the diffusion term 4π^2ν a sin z grows in proportion to ν: 0.079 at ν=0.01 and 0.790 at ν=0.1. a=0.2, φ=0.07.−1.5−1−0.500.511.500.20.40.60.81xsν = 0 (convective only)ν = 0.01ν = 0.05ν = 0.1
Figure 2 · The source s(x)s(x) that the same u∗u^* needs at different viscosities. For ν=0\nu=0 only the convective part remains (dashed); the amplitude of the diffusion term 4π2νa sin⁡z4\pi^2\nu a\,\sin z grows in proportion to ν\nu: 0.079 at ν=0.01\nu=0.01 and 0.790 at ν=0.1\nu=0.1. a=0.2a=0.2, φ=0.07\varphi=0.07.
图 3 · 构造解的目标与梯度随设计的变化(J* 与 ν 无关)。左:J* 随相位 φ 的变化,三条线对应三个振幅 a。右:a=0.2 时三个梯度分量随 φ 的闭式曲线;圆点是默认设计。梯度分量满足 |∂ J*/∂ a| ≤ 1/(2π) ≈ 0.16、|∂ J*/∂φ| ≤ a,比 J* ≈ 1.5 小一个量级。1.441.461.481.51.521.541.5600.20.40.60.81φJ*a = 0.1a = 0.2a = 0.4−0.4−0.200.20.400.20.40.60.81φ梯度(a = 0.2)∂J*/∂a∂J*/∂φ∂J*/∂ν
图 3 · 构造解的目标与梯度随设计的变化(J∗J^* 与 ν\nu 无关)。左:J∗J^* 随相位 φ\varphi 的变化,三条线对应三个振幅 aa。右:a=0.2a=0.2 时三个梯度分量随 φ\varphi 的闭式曲线;圆点是默认设计。梯度分量满足 ∣∂J∗/∂a∣≤1/(2π)≈0.16|\partial J^*/\partial a|\le1/(2\pi)\approx0.16、∣∂J∗/∂φ∣≤a|\partial J^*/\partial\varphi|\le a,比 J∗≈1.5J^*\approx1.5 小一个量级。
Figure 3 · The objective and gradient of the manufactured solution as functions of the design (J* does not depend on ν). Left: J* against the phase φ for three amplitudes a. Right: the closed-form curves of the three gradient components against φ at a=0.2; the dots are the default design. The gradient components satisfy |∂ J*/∂ a| ≤ 1/(2π) ≈ 0.16 and |∂ J*/∂φ| ≤ a, an order of magnitude below J* ≈ 1.5.1.441.461.481.51.521.541.5600.20.40.60.81φJ*a = 0.1a = 0.2a = 0.4−0.4−0.200.20.400.20.40.60.81φgradient (a = 0.2)∂J*/∂a∂J*/∂φ∂J*/∂ν
Figure 3 · The objective and gradient of the manufactured solution as functions of the design (J∗J^* does not depend on ν\nu). Left: J∗J^* against the phase φ\varphi for three amplitudes aa. Right: the closed-form curves of the three gradient components against φ\varphi at a=0.2a=0.2; the dots are the default design. The gradient components satisfy ∣∂J∗/∂a∣≤1/(2π)≈0.16|\partial J^*/\partial a|\le1/(2\pi)\approx0.16 and ∣∂J∗/∂φ∣≤a|\partial J^*/\partial\varphi|\le a, an order of magnitude below J∗≈1.5J^*\approx1.5.

自己动手:改变 aa、φ\varphi、ν\nu,看精确解、两部分通量和源项怎样变,并核对闭式的目标与梯度;再用下面的播放器,一步一步看源项是怎样由 u∗u^* 造出来的。

Try it yourself: change aa, φ\varphi and ν\nu, see how the exact solution, the two parts of the flux and the source change, and check the closed-form objective and gradient; then use the player below to watch the source being built from u∗u^* step by step.

先看一眼后面要反复用到的结论:解几乎感觉不到黏性(图 1),但它的灵敏度感觉得到。目标的伴随场 λ\lambda(第 11、12、16 节与附录 A)在 x=0x=0 处有一个宽度约 ν/u\nu/u 的边界层,ν\nu 越小越陡。离散伴随 ψ\psi(第 11 节)只定义在节点上:在内部节点上它近似 λ(xj)\lambda(x_j)(图中的圆圈),而只有节点落进层里,它才能表示这个层的形状。默认网格(N=8N=8,ν=0.01\nu=0.01)上,第一个内部节点 x1=0.125x_1=0.125 远在层外:ψ1=−1.709\psi_1=−1.709,而 λ(x1)=−1.416\lambda(x_1)=−1.416,相差 0.29;其余内部节点上的差都不超过 0.093。(两端的 ψ0\psi_0、ψN\psi_N 是两个约束行的乘子,不是 λ\lambda 的值,图里不画;第 11 节说明它们是什么。)

A look ahead at a result used again and again: the solution hardly feels the viscosity (Figure 1), but its sensitivity does. The adjoint field λ\lambda of the objective (Sections 11, 12, 16 and Appendix A) has a boundary layer of width about ν/u\nu/u at x=0x=0, steeper for smaller ν\nu. The discrete adjoint ψ\psi (Section 11) is defined at the nodes only: at the interior nodes it approximates λ(xj)\lambda(x_j) (the circles in the figure), and it can show the shape of such a layer only if nodes fall inside it. On the default mesh (N=8N=8, ν=0.01\nu=0.01) the first interior node x1=0.125x_1=0.125 is far outside the layer: ψ1=−1.709\psi_1=−1.709 while λ(x1)=−1.416\lambda(x_1)=−1.416, a difference of 0.29; at the other interior nodes the difference is at most 0.093. (The end values ψ0\psi_0, ψN\psi_N are the multipliers of the two constraint rows, not values of λ\lambda, so they are not drawn; Section 11 explains what they are.)

图 4 · 前瞻:连续伴随 λ(-uλ_x-νλ_xx=-(1+x),λ(0)=λ(1)=0)在 ν=0.1, 0.03, 0.01 下的解(独立的谱方法求得)。x=0 处的层随 ν 减小而变陡:λ_x(0)=−13.53, −47.28, −142.7。圆圈:默认网格上离散伴随 ψ_j 在内部节点处的值(ν=0.01)。−1.5−1−0.5000.20.40.60.81xλν = 0.1ν = 0.03ν = 0.01ψj​(N = 8,ν = 0.01,内部节点)
图 4 · 前瞻:连续伴随 λ\lambda(−uλx−νλxx=−(1+x)-u\lambda_x-\nu\lambda_{xx}=-(1+x),λ(0)=λ(1)=0\lambda(0)=\lambda(1)=0)在 ν=0.1, 0.03, 0.01\nu=0.1,\,0.03,\,0.01 下的解(独立的谱方法求得)。x=0x=0 处的层随 ν\nu 减小而变陡:λx(0)=−13.53, −47.28, −142.7\lambda_x(0)=−13.53,\ −47.28,\ −142.7。圆圈:默认网格上离散伴随 ψj\psi_j 在内部节点处的值(ν=0.01\nu=0.01)。
Figure 4 · A look ahead: the continuous adjoint λ (-uλ_x-νλ_xx=-(1+x), λ(0)=λ(1)=0) for ν=0.1, 0.03, 0.01 (from an independent spectral solver). The layer at x=0 steepens as ν decreases: λ_x(0)=−13.53, −47.28, −142.7. Circles: the discrete adjoint ψ_j of the default mesh at its interior nodes (ν=0.01).−1.5−1−0.5000.20.40.60.81xλν = 0.1ν = 0.03ν = 0.01ψj​ (N = 8, ν = 0.01, interior nodes)
Figure 4 · A look ahead: the continuous adjoint λ\lambda (−uλx−νλxx=−(1+x)-u\lambda_x-\nu\lambda_{xx}=-(1+x), λ(0)=λ(1)=0\lambda(0)=\lambda(1)=0) for ν=0.1, 0.03, 0.01\nu=0.1,\,0.03,\,0.01 (from an independent spectral solver). The layer at x=0x=0 steepens as ν\nu decreases: λx(0)=−13.53, −47.28, −142.7\lambda_x(0)=−13.53,\ −47.28,\ −142.7. Circles: the discrete adjoint ψj\psi_j of the default mesh at its interior nodes (ν=0.01\nu=0.01).

这个方程用来做什么

What this equation is for

黏性 Burgers 方程保留了流体动量方程的非线性对流项 u uxu\,u_x,又带上分子黏性项 −νuxx-\nu u_{xx},是最简单的“对流加扩散”非线性方程。本课程把它放在无黏 Burgers 与一维 Navier–Stokes 之间,原因有五:

The viscous Burgers equation keeps the nonlinear convection term u uxu\,u_x of the momentum equation and adds the molecular viscosity term −νuxx-\nu u_{xx}: it is the simplest nonlinear convection–diffusion equation. The course puts it between the inviscid Burgers pages and the 1-D Navier–Stokes pages, for five reasons:

  • 小。默认网格只有 9 个未知量(8+1 个节点值,其中两个由边界约束给定),每个数组和矩阵都能放在页面上,语句播放器也读得过来。Small. The default mesh has only 9 unknowns (8+1 nodal values, two of which the boundary constraints fix), so every array and matrix fits on the page and the statement players stay readable.
  • 非线性。数值通量对迹的偏导 cL=qL/2+1c_L=q_L/2+1 随状态变化,所以线性化(Jacobian)依赖于它取在哪个状态;切线与伴随都取在收敛的原始解上。Nonlinear. The derivative of the numerical flux with respect to a trace, cL=qL/2+1c_L=q_L/2+1, changes with the state, so the linearisation (the Jacobian) depends on where it is taken; the tangent and the adjoint are both evaluated at the converged primal solution.
  • 有精确答案可比。构造解给出每个设计下的精确解、精确目标和精确梯度,所以每个导数、每个收敛阶都能和真值比较。Exact answers to compare with. The manufactured solution gives the exact solution, objective and gradient for every design, so every derivative and every convergence rate can be compared with the truth.
  • 物理通量依赖导数 uxu_x。面通量要用面两侧节点值的差商近似 uxu_x,间距在每个面上都是 hh,边界面也不例外——这正是黏性 Navier–Stokes 页面每个面上要做的事,这里只有一个变量。The physical flux depends on the derivative uxu_x. A face flux needs a difference quotient of the two nodal values on its sides to approximate uxu_x, with the distance hh on every face, the boundary faces included: exactly what each face of the viscous Navier–Stokes pages does, here with one variable.
  • 设计进入物理通量和源项。a,φa,\varphi 改变源项和边界值,ν\nu 改变通量本身;第 12 节逐项分清这三条路径。The design enters the physical flux and the source. a,φa,\varphi change the source and the boundary values, ν\nu changes the flux itself; Section 12 separates the three paths one by one.

本页的数值、图和表来自本页的代码(模型在构建页面时与独立的 Python 实现逐项对照,第 15 节的大网格数据来自 Python 程序)。数值检查是验证证据,不是数学证明;本页不声称非线性方程或格式的存在性、唯一性或收敛定理。本页证明了的恒等式和性质,在它们出现的地方标明。

The numbers, figures and tables of this page come from the page's own code (the model is held to an independent Python implementation when the page is built, and the large-grid data of Section 15 come from the Python program). Numerical checks are verification evidence, not mathematical proofs; the page claims no existence, uniqueness or convergence theorem for the nonlinear equation or for the scheme. The identities and properties it does prove are marked where they occur.

第 2 节Section 2

网格:节点与对偶控制体

The mesh: nodes and dual volumes

本节实验:数一数,N=8N=8 的网格有几个节点、几个对偶控制体、几个面?每个内部面和每个边界面各读哪些节点?哪两个控制体只有一半宽?先答,再对照图 5。

Experiment: Count the nodes, the dual volumes and the faces of the mesh with N=8N=8 intervals. Which nodes does each interior face and each boundary face read, and which two dual volumes have only half the width? Answer first, then compare with Figure 5.

第 1 节给出了方程。本节把区间 [0,1][0,1] 分成 NN 个等宽的区间,宽度 h=1/Nh=1/N,把未知量放在区间的端点(网格节点)上,让每个节点管着它周围的一段对偶控制体,再说明页面存哪些数据。

Section 1 gave the equation. This section divides [0,1][0,1] into NN equal intervals of width h=1/Nh=1/N, puts the unknowns at the interval end points (the mesh nodes), gives each node the dual volume around it as its control volume, and says what the page stores.

节点、对偶控制体和面

Nodes, dual volumes and faces

节点 j=0,…,Nj=0,\dots,N 在 xj=jhx_j=jh。未知量 UjU_j 是解在这个节点上的点值,一共 N+1N+1 个,两端的节点也在其中:

Node j=0,…,Nj=0,\dots,N is at xj=jhx_j=jh. The unknown UjU_j is the point value of the solution at that node; there are N+1N+1 of them, the two end nodes included:

Uj≈u(xj),𝐔=(U0,…,UN)T∈ℝN+1.U_j\approx u(x_j),\qquad \mathbf U=(U_0,\dots,U_N)^T\in\mathbb R^{N+1}.

每个节点管着它周围的一段,即对偶控制体 Vj=[xj−h2, xj+h2]∩[0,1]V_j=[x_j-\tfrac h2,\,x_j+\tfrac h2]\cap[0,1],宽度是 Wj=hW_j=h(1≤j≤N−11\le j\le N-1),两端的 V0V_0 与 VNV_N 只有 W0=WN=h/2W_0=W_N=h/2。控制体之间的界面是面:面 ff(f=0,…,N−1f=0,\dots,N-1)在节点 ff 与节点 f+1f+1 的中点 xf+1/2=(f+12)hx_{f+1/2}=(f+\tfrac12)h,它是 VfV_f 的右面,也是 Vf+1V_{f+1} 的左面。一共 NN 个面,而且每个面两侧都有节点,最外面的两个面也不例外:没有面要去读给定值或半个间距的数据,第 3 节的面通量在边界面上没有特殊情形。

Each node controls the stretch around it, its dual volume Vj=[xj−h2, xj+h2]∩[0,1]V_j=[x_j-\tfrac h2,\,x_j+\tfrac h2]\cap[0,1], of width Wj=hW_j=h (1≤j≤N−11\le j\le N-1); the two end volumes V0V_0 and VNV_N have only W0=WN=h/2W_0=W_N=h/2. The interfaces between the volumes are the faces: face ff (f=0,…,N−1f=0,\dots,N-1) is the midpoint xf+1/2=(f+12)hx_{f+1/2}=(f+\tfrac12)h of the interval between node ff and node f+1f+1; it is the right face of VfV_f and the left face of Vf+1V_{f+1}. There are NN faces and every one of them has a node on each side, the two outermost included: no face reads a prescribed value or half an interval of data, and the face flux of Section 3 has no special case at a boundary face.

两个端点节点的未知量在向量里,但它们那一行的方程不是通量平衡:第 00 行和第 NN 行是边界约束 U0=uinU_0=u_{\rm in}、UN=uoutU_N=u_{\rm out}(第 4 节)。所以 N+1N+1 个未知量对应 N−1N-1 个通量平衡(内部节点的对偶控制体)加 2 个约束。本页的格式不需要穿过 x=0x=0 与 x=1x=1 的通量,因为约束已经给出了端点值,它也从不计算这样的通量。

The two end nodes are unknowns of the vector, but the equations of their rows are not flux balances: row 00 and row NN are the boundary constraints U0=uinU_0=u_{\rm in}, UN=uoutU_N=u_{\rm out} (Section 4). So the N+1N+1 unknowns are matched by N−1N-1 flux balances (the dual volumes of the interior nodes) plus 2 constraints. The scheme needs no flux through the ends x=0x=0 and x=1x=1 of the interval, because the constraints already fix the end values, and it never computes one.

图 5 · 网格与数据(N=8)。节点 j(点)存储点值 U_j,它的对偶控制体 V_j 是灰色的一段;面 f 夹在节点 f 与 f+1 之间,读这两个节点的数据(再加重构需要的邻居,第 3 节)。两端的节点(方块)是约束行,U_0=u_in、U_N=u_out,它们的控制体只有半宽 h/2(第 4 节);包括面 0 与面 N-1 在内,每个面的两侧都是节点,间距 d_f=h。f = 0f = 1f = 2f = 3f = 4f = 5f = 6f = 7U0​j = 0U1​j = 1U2​j = 2U3​j = 3U4​j = 4U5​j = 5U6​j = 6U7​j = 7U8​j = 8uin​uout​节点 j 在 xj​ = j h,对偶控制体 Vj​ 在它周围,存点值 Uj​面 f 在 xf+1/2​ = (f + 1/2) h,夹在节点 f 与 f+1 之间;方块是约束行内部面 f = 3:读两侧的两个节点值,相距 df​ = h边界面 f = 0:节点 0 与 1 同样相距 h,没有半个间距W0​ = h/2W1​ = h
图 5 · 网格与数据(N=8N=8)。节点 jj(点)存储点值 UjU_j,它的对偶控制体 VjV_j 是灰色的一段;面 ff 夹在节点 ff 与 f+1f+1 之间,读这两个节点的数据(再加重构需要的邻居,第 3 节)。两端的节点(方块)是约束行,U0=uinU_0=u_{\rm in}、UN=uoutU_N=u_{\rm out},它们的控制体只有半宽 h/2h/2(第 4 节);包括面 00 与面 N−1N-1 在内,每个面的两侧都是节点,间距 df=hd_f=h。
Figure 5 · The mesh and its data (N=8). Node j (dot) stores the point value U_j, and its dual volume V_j is the grey stretch around it; face f lies between nodes f and f+1 and reads the data of these two nodes (plus the neighbours that the reconstruction needs, ). The end nodes (squares) are the constraint rows U_0=u_in, U_N=u_out and their volumes have only the half width h/2 (); every face, face 0 and face N-1 included, has a node on each side, a distance d_f=h apart.f = 0f = 1f = 2f = 3f = 4f = 5f = 6f = 7U0​j = 0U1​j = 1U2​j = 2U3​j = 3U4​j = 4U5​j = 5U6​j = 6U7​j = 7U8​j = 8uin​uout​node j at xj​ = j h, its dual volume Vj​ around it, the point value Uj​face f at xf+1/2​ = (f + 1/2) h between nodes f and f+1; the squares are the constraint rowsinterior face f = 3: two nodal values, df​ = h apartboundary face f = 0: nodes 0 and 1 are also h apartW0​ = h/2W1​ = h
Figure 5 · The mesh and its data (N=8N=8). Node jj (dot) stores the point value UjU_j, and its dual volume VjV_j is the grey stretch around it; face ff lies between nodes ff and f+1f+1 and reads the data of these two nodes (plus the neighbours that the reconstruction needs, Section 3). The end nodes (squares) are the constraint rows U0=uinU_0=u_{\rm in}, UN=uoutU_N=u_{\rm out} and their volumes have only the half width h/2h/2 (Section 4); every face, face 00 and face N−1N-1 included, has a node on each side, a distance df=hd_f=h apart.

先看网格是怎样一步一步搭起来的:

First see how the mesh is built, step by step:

选一个面或一个节点,看它读哪些未知量;再换一种重构,数一数:

Select a face or a node and see which unknowns it reads; then change the reconstruction and count:

未知量的精确值:节点值,不是平均值

The exact values of the unknowns: nodal values, not means

对构造解,未知量 UjU_j 的精确值就是解在节点上的取值,不需要任何平均:

For the manufactured solution the exact value of the unknown UjU_j is simply the solution at the node, with no averaging:

Ujexact=u∗(xj)=1+a sin⁡(2π(xj−φ)),j=0,…,N.U_j^{\rm exact}=u^*(x_j)=1+a\,\sin\bigl(2\pi(x_j-\varphi)\bigr),\qquad j=0,\dots,N.

状态的误差始终拿离散解和这些精确节点值比较(它们也是 Newton 迭代的初值)。格心页的未知量是另一种对象:单元 ii 上解的平均值。对这个正弦解,振荡部分的平均值是它在单元中心处的值乘以 sinc⁡(h)=sin⁡(πh)/(πh)\operatorname{sinc}(h)=\sin(\pi h)/(\pi h),等于把振幅从 aa 缩小为 a sinc⁡(h)a\,\operatorname{sinc}(h):

The errors of the state are always measured between the discrete solution and these exact nodal values (which are also the initial guess of the Newton iteration). The unknown of the cell-centred page is a different object: the mean value of the solution over a cell ii. For this sine wave the mean of the oscillating part over a cell is its value at the cell centre times sinc⁡(h)=sin⁡(πh)/(πh)\operatorname{sinc}(h)=\sin(\pi h)/(\pi h), which reduces the amplitude from aa to a sinc⁡(h)a\,\operatorname{sinc}(h):

⟨u∗⟩i=1+a sinc⁡(h) sin⁡(2π(xi−φ)),xi=(i+12)h.\langle u^*\rangle_i=1+a\,\operatorname{sinc}(h)\,\sin\bigl(2\pi(x_i-\varphi)\bigr),\qquad x_i=(i+\tfrac12)h.

默认网格上 sinc⁡(h)=0.9745\operatorname{sinc}(h)=0.9745,振幅缩小 2.6%,平均值与中心值最多差 a(1−sinc⁡h)=0.0051a(1-\operatorname{sinc}h)=0.0051;N=16N=16 与 3232 时是 0.0013 与 0.00032,按 h2h^2 缩小(图 6)。所以同一个 u∗u^* 在两页里给出的未知量向量并不相同,两页的状态误差是离各自精确向量(这里是采样值,那里是平均值)的距离:同一个 NN 下两个状态误差不是同一个量的误差。两页都定义的量,如目标 JhJ_h 和它的梯度,则可以直接比较。

At the defaults sinc⁡(h)=0.9745\operatorname{sinc}(h)=0.9745, a reduction of the amplitude by 2.6%, and a mean differs from the value at the centre by at most a(1−sinc⁡h)=0.0051a(1-\operatorname{sinc}h)=0.0051; at N=16N=16 and 3232 it is 0.0013 and 0.00032, shrinking like h2h^2 (Figure 6). So the same u∗u^* gives different unknown vectors on the two pages, and each page measures its state errors from its own exact vector (samples here, means there): two state errors at the same NN are not errors of one quantity. What both pages define, such as the objective JhJ_h and its gradient, can be compared directly.

图 6 · 同一个 u* 的两种未知量。上:本页的未知量是节点值(点,N+1=9 个,含两端),格心页的是单元平均值(方块,N=8 个,在单元中心)。下:平均值减去单元中心的值,a(sinch-1)sin z,N=8, 16, 32:振幅 0.0051、0.0013、0.00032,按 h^2 缩小。0.70.80.911.11.21.300.20.40.60.81xuu*本页:节点值(9 个)格心页:单元平均值(8 个)−0.006−0.004−0.00200.0020.0040.00600.20.40.60.81x平均值 − 中心值N = 8N = 16N = 32
图 6 · 同一个 u∗u^* 的两种未知量。上:本页的未知量是节点值(点,N+1=9N+1=9 个,含两端),格心页的是单元平均值(方块,N=8N=8 个,在单元中心)。下:平均值减去单元中心的值,a(sinc⁡h−1)sin⁡za(\operatorname{sinc}h-1)\sin z,N=8, 16, 32N=8,\,16,\,32:振幅 0.0051、0.0013、0.00032,按 h2h^2 缩小。
Figure 6 · Two kinds of unknown for the same u*. Top: the unknowns of this page are nodal values (dots, N+1=9 of them, ends included), those of the cell-centred page are cell means (squares, N=8 of them, at the cell centres). Bottom: the mean minus the value at the cell centre, a(sinch-1)sin z, for N=8, 16, 32: amplitudes 0.0051, 0.0013, 0.00032, shrinking like h^2.0.70.80.911.11.21.300.20.40.60.81xuu*this page: nodal values (9)cell-centred page: cell means (8)−0.006−0.004−0.00200.0020.0040.00600.20.40.60.81xmean − centre valueN = 8N = 16N = 32
Figure 6 · Two kinds of unknown for the same u∗u^*. Top: the unknowns of this page are nodal values (dots, N+1=9N+1=9 of them, ends included), those of the cell-centred page are cell means (squares, N=8N=8 of them, at the cell centres). Bottom: the mean minus the value at the cell centre, a(sinc⁡h−1)sin⁡za(\operatorname{sinc}h-1)\sin z, for N=8, 16, 32N=8,\,16,\,32: amplitudes 0.0051, 0.0013, 0.00032, shrinking like h2h^2.

记号

Notation

默认设置:N=8N=8,无限制器线性重构,D=(a,φ,ν)=(0.2, 0.07, 0.01)D=(a,\varphi,\nu)=(0.2,\ 0.07,\ 0.01),即页首控件的初始值;图和文字除另有说明外都取默认设置。

Default settings: N=8N=8, unlimited linear reconstruction and D=(a,φ,ν)=(0.2, 0.07, 0.01)D=(a,\varphi,\nu)=(0.2,\ 0.07,\ 0.01), the initial values of the controls at the top; the figures and the text use them unless another setting is stated.

按伴随优化文献的通常写法,设计变量记作 D=(a,φ,ν)D=(a,\varphi,\nu),分量 D0=aD_0=a、D1=φD_1=\varphi、D2=νD_2=\nu。残差是 R(𝐔,D)∈ℝN+1R(\mathbf U,D)\in\mathbb R^{N+1}(两端两行是约束),状态 Jacobian 是 A=R𝐔A=R_{\mathbf U},设计 Jacobian 是 RDR_D,离散目标是 JhJ_h,伴随变量是 ψ\psi。

As is usual in the adjoint-optimization literature, the design variables are written D=(a,φ,ν)D=(a,\varphi,\nu), with components D0=aD_0=a, D1=φD_1=\varphi, D2=νD_2=\nu. The residual is R(𝐔,D)∈ℝN+1R(\mathbf U,D)\in\mathbb R^{N+1} (the two end rows are the constraints), the state Jacobian is A=R𝐔A=R_{\mathbf U}, the design Jacobian is RDR_D, the discrete objective is JhJ_h and the adjoint variable is ψ\psi.

切线(前向,tangent)与伴随(反向,adjoint)一律用自动微分的记号:程序变量 xx 的切线写 x˙\dot x,伴随写 xˉ\bar x,伴随累加写 xˉ+=…\bar x\mathrel{\text{+=}}\dots,伴随语句按逆序执行;x˙\dot x 与 xˉ\bar x 一一对应 Tapenade 等工具里的变量 x_d 与 x_b,本页的伪代码就用这些名字。变分符号 δ\delta 只出现在连续推导里(附录 A 与第 16 节中的连续推导:连续函数的变分);Newton 与 GS 的迭代增量写 Δ\Delta。

The tangent (forward) and the adjoint (reverse) always use the notation of automatic differentiation: the forward derivative of a program variable xx is x˙\dot x, its adjoint is xˉ\bar x, an adjoint accumulation is written xˉ+=…\bar x\mathrel{\text{+=}}\dots and the statements run in reverse order. They correspond one to one to the variables x_d and x_b of AD tools such as Tapenade, and the pseudocode of this page uses these names. The variation symbol δ\delta appears only in continuous derivations (Appendix A and the continuous derivation of Section 16: variations of continuous functions); the increments of the Newton and GS iterations are written Δ\Delta.

有两个与黏性有关的量,不要混淆:物理黏性 ν\nu(设计分量 D2D_2,进入物理通量 −νux-\nu u_x);Rusanov 数值通量里的耗散(第 3 节),其波速 α=2\alpha=2 是固定常数,一阶格式里它等效于随网格变化的人工黏性 hh,不是设计变量。

Two quantities that both look like a viscosity must not be confused: the physical viscosity ν\nu (the design component D2D_2, which enters the physical flux −νux-\nu u_x) and the dissipation of the Rusanov numerical flux (Section 3), whose speed α=2\alpha=2 is a fixed constant and which acts at first order as an artificial viscosity hh that changes with the mesh; it is not a design variable.

本页的主要符号

The main symbols of this page

符号Symbol含义Meaning大小Size定义处Defined in
N, h, xj, xf+1/2N,\ h,\ x_j,\ x_{f+1/2}区间数、间距 h=1/Nh=1/N、节点坐标 xj=jhx_j=jh、面坐标intervals, spacing h=1/Nh=1/N, node coordinates xj=jhx_j=jh, face coordinates—第 2 节Section 2
Vj, WjV_j,\ W_j节点 jj 的对偶控制体及其宽度(内部 hh,两端 h/2h/2)dual volume of node jj and its width (hh inside, h/2h/2 at the ends)N+1N+1第 2 节Section 2
𝐔, Uj\mathbf U,\ U_j状态:节点上的点值state: the point values at the nodesN+1N+1第 2 节Section 2
D=(a,φ,ν)D=(a,\varphi,\nu)设计:振幅、相位、黏性design: amplitude, phase, viscosity3第 1 节Section 1
R(𝐔,D), RjR(\mathbf U,D),\ R_j积分残差(不除以 hh);第 00、NN 行是边界约束integrated residual (not divided by hh); rows 00 and NN are the boundary constraintsN+1N+1第 4、5 节Sections 4 and 5
Hf=Hc+HvH_f=H^c+H^v面通量:对流部分加黏性部分face flux: convective plus viscous partNN第 3 节Section 3
qL, qR, UL, UR, df, κfq_L,\ q_R,\ U_L,\ U_R,\ d_f,\ \kappa_f迹、未重构状态、距离(df=hd_f=h)、ν/df\nu/d_ftraces, raw states, distance (df=hd_f=h), ν/df\nu/d_f—第 3 节Section 3
σj, lj, rj\sigma_j,\ l_j,\ r_j节点 jj 的斜率与两个单侧差slope at node jj and the two one-sided differencesN+1N+1第 3 节Section 3
cL, cRc_L,\ c_RHcH^c 对迹的偏导derivatives of HcH^c with respect to the tracesNN第 3 节Section 3
Qf, SjQ_f,\ S_j精确通量 Qf=q∗(xf+1/2)Q_f=q^*(x_{f+1/2}) 与积分源项 Sj=Qj−Qj−1S_j=Q_j-Q_{j-1}exact flux Qf=q∗(xf+1/2)Q_f=q^*(x_{f+1/2}) and integrated source Sj=Qj−Qj−1S_j=Q_j-Q_{j-1}N, N−1N,\ N-1第 3 节Section 3
uin, uoutu_{\rm in},\ u_{\rm out}给定的两端值(只进入约束行)prescribed end values (they enter the constraint rows only)2第 1、4 节Sections 1 and 4
A=R𝐔, RDA=R_{\mathbf U},\ R_D状态与设计 Jacobianstate and design Jacobians(N+1)×(N+1), (N+1)×3(N+1)\times(N+1),\ (N+1)\times3第 6、8 节Sections 6 and 8
Jh=wT𝐔, g=wJ_h=w^T\mathbf U,\ g=w离散目标与状态梯度;wj=Wj(1+xj)w_j=W_j(1+x_j)discrete objective and state gradient; wj=Wj(1+xj)w_j=W_j(1+x_j)1, N+11,\ N+1第 2、7 节Sections 2 and 7
v=𝐔˙, D˙=ekv=\dot{\mathbf U},\ \dot D=e_k切线与设计种子tangent and design seedN+1, 3N+1,\ 3第 8、10 节Sections 8 and 10
ψ, ψ0, ψN, Dˉ\psi,\ \psi_0,\ \psi_N,\ \bar D伴随变量、两个约束行的乘子、设计伴随(梯度)adjoint variable, the multipliers of the two constraint rows, design adjoint (the gradient)N+1, 1, 1, 3N+1,\ 1,\ 1,\ 3第 9、11 节Sections 9 and 11
λ\lambda连续伴随场the continuous adjoint field—第 1、11、12、16 节与附录 ASections 1, 11, 12 and 16 and Appendix A
Peh=uinh/ν\mathrm{Pe}_h=u_{\rm in}h/\nu网格 Péclet 数mesh Péclet number—第 1、3 节Sections 1 and 3

下标的约定:jj 总是节点(以及它的对偶控制体 VjV_j),ff 总是面;xj=jhx_j=jh 是节点 jj 的坐标,面 ff 在 xf+1/2=(f+12)hx_{f+1/2}=(f+\tfrac12)h,夹在节点 ff 与 f+1f+1 之间(N=8N=8 时面 44 在 x9/2=0.5625x_{9/2}=0.5625)。伪代码里的数组 s[j] 存斜率 σj\sigma_j,它不是第 1 节的源项 s(x)s(x)。

Subscript convention: jj always names a node (and its dual volume VjV_j) and ff a face; xj=jhx_j=jh is the coordinate of node jj, and face ff is at xf+1/2=(f+12)hx_{f+1/2}=(f+\tfrac12)h, between nodes ff and f+1f+1 (at N=8N=8 face 44 is at x9/2=0.5625x_{9/2}=0.5625). In the pseudocode the array s[j] stores the slope σj\sigma_j; it is not the source s(x)s(x) of Section 1.

默认网格上的数组(N=8N=8)

The arrays on the default mesh (N=8N=8)

节点 jjNode jj坐标 xjx_jCoordinate xjx_j对偶控制体宽度 WjW_jDual-volume width WjW_j目标权重 wj=Wj(1+xj)w_j=W_j(1+x_j)Objective weight wj=Wj(1+xj)w_j=W_j(1+x_j)精确节点值 u∗(xj)u^*(x_j)Exact nodal value u∗(xj)u^*(x_j)离散解 UjU_j(无限制器线性)Discrete UjU_j (unlimited linear)
00.00000.06250.062500.914840.91484
10.12500.12500.140631.067751.07014
20.25000.12500.156251.180971.17081
30.37500.12500.171881.188181.16556
40.50000.12500.187501.085161.05739
50.62500.12500.203130.932250.91290
60.75000.12500.218750.819030.82184
70.87500.12500.234380.811820.83279
81.00000.06250.125000.914840.91484

第 00 行和第 NN 行的 UjU_j 等于给定值 uinu_{\rm in}、uoutu_{\rm out}(约束行使它们在舍入误差内精确),其余是通量平衡的解。权重 wjw_j 是第 7 节离散目标 Jh=∑jwjUjJ_h=\sum_jw_jU_j 的系数,也是状态梯度 g=wg=w(目标对状态的导数;伴随方程 ATψ=−gA^T\psi=-g 的右端是 −g-g)。它们正是 ∫01(1+x)u dx\int_0^1(1+x)u\,\mathrm dx 的梯形公式的权重:每个节点按它的对偶控制体的宽度计数,两端是半宽(图 7)。

The values UjU_j in rows 00 and NN equal the prescribed uinu_{\rm in}, uoutu_{\rm out} (the constraint rows make them exact up to rounding) and the others solve the flux balances. The weights wjw_j are the coefficients of the discrete objective Jh=∑jwjUjJ_h=\sum_jw_jU_j of Section 7 and also the state gradient g=wg=w (the right-hand side of the adjoint equation ATψ=−gA^T\psi=-g is −g-g). They are exactly the weights of the trapezoid rule for ∫01(1+x)u dx\int_0^1(1+x)u\,\mathrm dx: each node counts with the width of its dual volume, half of it at the two ends (Figure 7).

作用在精确节点值上,Jh(u∗)J_h(u^*) 就是 (1+x)u∗(1+x)u^* 的梯形公式,它与 J∗J^* 的差可以写出来:梯形公式的误差是 h212[f′]01+O(h4)\tfrac{h^2}{12}\bigl[f'\bigr]_0^1+O(h^4),而 f=(1+x)u∗f=(1+x)u^* 的导数在两端的差是 f′(1)−f′(0)=ux∗(0)f'(1)-f'(0)=u^*_x(0)(u∗u^* 以 1 为周期,只剩权重 1+x1+x 的那一项):

Applied to the exact nodal values, Jh(u∗)J_h(u^*) is the trapezoid rule for (1+x)u∗(1+x)u^*, and its difference from J∗J^* can be written down: the error of the trapezoid rule is h212[f′]01+O(h4)\tfrac{h^2}{12}\bigl[f'\bigr]_0^1+O(h^4), and for f=(1+x)u∗f=(1+x)u^* the jump of the derivative between the two ends is f′(1)−f′(0)=ux∗(0)f'(1)-f'(0)=u^*_x(0) (u∗u^* has period 1, so only the part from the weight 1+x1+x is left):

Jh(u∗)−J∗=h212 ux∗(0)+O(h4),ux∗(0)=2πacos⁡2πφ.J_h(u^*)-J^*=\frac{h^2}{12}\,u^*_x(0)+O(h^4),\qquad u^*_x(0)=2\pi a\cos 2\pi\varphi.

默认设置下 ux∗(0)=1.1370u^*_x(0)=1.1370,Jh(u∗)=1.4726944J_h(u^*)=1.4726944,J∗=1.4711985J^*=1.4711985,差 1.496×10−31.496\times10^{−3},公式给出 1.481×10−31.481\times10^{−3}(比值 1.0104)。这是 JhJ_h 本身的离散误差:即使状态是精确的,离散目标也比 J∗J^* 大约差这么多,它在第 15、16 节里作为梯度误差的一部分重新出现。(这个公式是用 Euler–Maclaurin 公式推出的,本页对它做了数值核对,没有给出严格证明。)

At the defaults ux∗(0)=1.1370u^*_x(0)=1.1370, Jh(u∗)=1.4726944J_h(u^*)=1.4726944 and J∗=1.4711985J^*=1.4711985; the difference is 1.496×10−31.496\times10^{−3} and the formula gives 1.481×10−31.481\times10^{−3} (ratio 1.0104). This is the discretisation error of JhJ_h itself: even with an exact state the discrete objective differs from J∗J^* by about this much, and it reappears in Sections 15 and 16 as part of the gradient error. (The formula follows from the Euler–Maclaurin formula; the page checks it numerically and gives no rigorous proof of it.)

图 7 · 离散目标的权重就是梯形公式。上:被积函数 (1+x)u*(x)(实线)和它在 N=8 个区间上的梯形(阴影);节点值 (1+x_j)u*(x_j) 是点。下:对偶控制体的宽度 W_j(方块:h/2、h、…、h、h/2)和权重 w_j=W_j(1+x_j)(柱)。梯形面积之和是 J_h(u*)=1.4726944,精确的 J*=1.4711985。00.511.5200.20.40.60.81x被积函数(1 + x) u*(x)节点上的值 (1 + xj​) u*(xj​)00.050.10.150.20.250.300.20.40.60.81xwj​权重 wj​ = Wj​ (1 + xj​)对偶控制体的宽度 Wj​
图 7 · 离散目标的权重就是梯形公式。上:被积函数 (1+x)u∗(x)(1+x)u^*(x)(实线)和它在 N=8N=8 个区间上的梯形(阴影);节点值 (1+xj)u∗(xj)(1+x_j)u^*(x_j) 是点。下:对偶控制体的宽度 WjW_j(方块:h/2h/2、hh、…、hh、h/2h/2)和权重 wj=Wj(1+xj)w_j=W_j(1+x_j)(柱)。梯形面积之和是 Jh(u∗)=1.4726944J_h(u^*)=1.4726944,精确的 J∗=1.4711985J^*=1.4711985。
Figure 7 · The weights of the discrete objective are the trapezoid rule. Top: the integrand (1+x)u*(x) (solid) and its trapezoids on the N=8 intervals (shaded); the nodal values (1+x_j)u*(x_j) are the dots. Bottom: the widths W_j of the dual volumes (squares: h/2, h, …, h, h/2) and the weights w_j=W_j(1+x_j) (bars). The trapezoid areas add up to J_h(u*)=1.4726944 against the exact J*=1.4711985.00.511.5200.20.40.60.81xintegrand(1 + x) u*(x)nodal values (1 + xj​) u*(xj​)00.050.10.150.20.250.300.20.40.60.81xwj​weight wj​ = Wj​ (1 + xj​)dual-volume width Wj​
Figure 7 · The weights of the discrete objective are the trapezoid rule. Top: the integrand (1+x)u∗(x)(1+x)u^*(x) (solid) and its trapezoids on the N=8N=8 intervals (shaded); the nodal values (1+xj)u∗(xj)(1+x_j)u^*(x_j) are the dots. Bottom: the widths WjW_j of the dual volumes (squares: h/2h/2, hh, …, hh, h/2h/2) and the weights wj=Wj(1+xj)w_j=W_j(1+x_j) (bars). The trapezoid areas add up to Jh(u∗)=1.4726944J_h(u^*)=1.4726944 against the exact J∗=1.4711985J^*=1.4711985.

后面各节要用到的所有数组和它们的形状都在图 8 里:左边是向量,右边是矩阵(颜色表示正负与大小,蓝正橙负)。它们都是本页在默认设计 DD 和 N=8N=8 下真实算出的量;AA 是 (N+1)×(N+1)(N+1)\times(N+1) 的五对角矩阵,第 00 行与第 NN 行是单位行(约束),RDR_D 只有 3 列,所以一次伴随求解(右端项 −g-g)给出梯度的全部 3 个分量,而切线求解要做 3 次。

All the arrays that the later sections use, with their shapes, are in Figure 8: vectors on the left, matrices on the right (colour shows sign and size: blue positive, orange negative). They are real quantities of this page at the default design DD and N=8N=8: AA is an (N+1)×(N+1)(N+1)\times(N+1) five-band matrix whose rows 00 and NN are identity rows (the constraints), and RDR_D has only 3 columns, so one adjoint solve (right-hand side −g-g) gives all 3 design components while the tangent solves must be done 3 times.

图 8 · 页面存储的数组与形状(默认设计,N=8,无限制器线性重构):设计 D、状态 U、残差 R、面通量 H、权重 w、目标 J_h;右边是 A=R_(U)(紫框是约束行)、R_D、三个切线解 v_k 和伴随 ψ 的真实数值。设计 D(3)aφν状态 U(N+1,节点值)残差 R(N+1)面通量 H(N)权重 w = g(N+1)目标 Jh​(1)A = RU​((N+1)×(N+1),五对角)012345678012345678设计 Jacobian RD​((N+1)×3)012012345678伴随 ψ(N+1)0123456780切线解 vk​(k = 0, 1, 2)012345678012紫框:第 0 行与第 N 行,约束行
图 8 · 页面存储的数组与形状(默认设计,N=8N=8,无限制器线性重构):设计 DD、状态 𝐔\mathbf U、残差 RR、面通量 HH、权重 ww、目标 JhJ_h;右边是 A=R𝐔A=R_{\mathbf U}(紫框是约束行)、RDR_D、三个切线解 vkv_k 和伴随 ψ\psi 的真实数值。
Figure 8 · The arrays the page stores and their shapes (default design, N=8, unlimited linear reconstruction): design D, state U, residual R, face fluxes H, weights w, objective J_h; on the right the real values of A=R_(U) (the violet frames are the constraint rows), R_D, the three tangents v_k and the adjoint ψ.design D (3)aφνstate U (N+1, nodal values)residual R (N+1)face fluxes H (N)weights w = g (N+1)objective Jh​ (1)A = RU​ ((N+1)×(N+1), five bands)012345678012345678design Jacobian RD​ ((N+1)×3)012012345678adjoint ψ (N+1)0123456780tangents vk​ (k = 0, 1, 2)012345678012violet frames: rows 0 and N, the constraint rows
Figure 8 · The arrays the page stores and their shapes (default design, N=8N=8, unlimited linear reconstruction): design DD, state 𝐔\mathbf U, residual RR, face fluxes HH, weights ww, objective JhJ_h; on the right the real values of A=R𝐔A=R_{\mathbf U} (the violet frames are the constraint rows), RDR_D, the three tangents vkv_k and the adjoint ψ\psi.
第 3 节Section 3

面上的通量:对流、黏性与重构

The flux on a face: convection, viscosity and reconstruction

本节实验:选定一个面和一种重构,这个面读哪几个节点?四个量 qL,qR,UL,URq_L,q_R,U_L,U_R 里哪些恰好等于节点值?先预测,再用本节的“一个面的量”面板(以及第 2 节的“一个面、一个节点读哪些数据”面板)验证。

Experiment: Select a face and a reconstruction: which nodes does the face read, and which of the four quantities qL,qR,UL,URq_L,q_R,U_L,U_R are nodal values? Predict first, then check with the panel “The quantities of one face” of this section (and “What a face and a node read” in Section 2).

第 2 节在区间上放好了节点和它们的对偶控制体。本节把方程写成对偶控制体上的通量差,用数值通量把面两侧的数据变成一个面通量(对流部分和黏性部分),再说明二阶格式怎样由节点值重构出面上的状态,以及这些公式精确满足的性质:耗散的恒等式、通量的相容性、导数与模板。

Section 2 placed the nodes and their dual volumes. This section writes the equation as a flux difference over a dual volume, turns the data on the two sides of a face into one face flux (a convective part and a viscous part), then shows how the second-order scheme reconstructs face states from the nodal values and what the formulas satisfy exactly: the identities of the dissipation, the consistency of the flux, the derivatives and the stencils.

从方程到通量差

From the equation to a flux difference

第 1 节的方程是 qx=sq_x=s,q=12u2−νuxq=\tfrac12u^2-\nu u_x。在内部节点 jj(1≤j≤N−11\le j\le N-1)的对偶控制体 VjV_j 上积分,它的两个面在 xj±1/2x_{j\pm1/2}:由微积分基本定理,通量的导数变成两端通量之差,等于控制体内的总源项:

The equation of Section 1 is qx=sq_x=s with q=12u2−νuxq=\tfrac12u^2-\nu u_x. Integrate it over the dual volume VjV_j of an interior node jj (1≤j≤N−11\le j\le N-1), whose two faces are at xj±1/2x_{j\pm1/2}: by the fundamental theorem of calculus the derivative of the flux becomes the difference of the end fluxes, which equals the total source in the volume:

q(xj+1/2)−q(xj−1/2)=∫xj−1/2xj+1/2s(x) dx=:Sj=Qj−Qj−1,Qf=q∗(xf+1/2;D).q\bigl(x_{j+1/2}\bigr)-q\bigl(x_{j-1/2}\bigr)=\int_{x_{j-1/2}}^{x_{j+1/2}}s(x)\,\mathrm dx=:S_j=Q_j-Q_{j-1},\qquad Q_f=q^*(x_{f+1/2};D).

对构造解,源项是 s=qx∗s=q^*_x,所以一个控制体里的总源项就是精确通量 QfQ_f 在它两个面上的差,不需要数值积分;第 5 节的残差用的就是这个精确的积分源项。两个端点的控制体 V0V_0、VNV_N 不做平衡:它们的行是边界约束(第 4 节),所以本页的格式没有 x=0x=0、x=1x=1 处的通量。离散化要做的只剩一件事:用面两侧节点的数据近似每个面上的通量(图 9)。

For the manufactured solution the source is s=qx∗s=q^*_x, so the total source of a volume is exactly the difference of the exact flux QfQ_f at its two faces, with no numerical quadrature; the residual of Section 5 uses this exact integrated source. The two end volumes V0V_0, VNV_N do no balance: their rows are the boundary constraints (Section 4), so the scheme has no flux through x=0x=0 or x=1x=1. What remains for the discretisation is to approximate the flux at each face from the data of the nodes on its two sides (Figure 9).

图 9 · 一个对偶控制体上的平衡(V_4,x[0.4375, 0.5625],默认设计)。上:源项 s(x) 在 V_4 上的面积(阴影)是 S_4=−0.14531。下:精确通量 q* 在两个面上的值 Q_3=0.66732、Q_4=0.52202 之差等于这个面积;圆圈是收敛解的数值通量 H_3=0.66252、H_4=0.51721:它们与各自的 Q 都相差 c_H=−0.00481(两个面上的差相同,第 5 节)。−1−0.500.5100.20.40.60.81xsS4​ = −0.14531V4​源项 s(x)0.30.40.50.60.70.800.20.40.60.81xqQ4​ − Q3​ = −0.14531精确通量 q*数值通量 Hf​(收敛解,N = 8)
图 9 · 一个对偶控制体上的平衡(V4V_4,x∈[0.4375, 0.5625]x\in[0.4375,\,0.5625],默认设计)。上:源项 s(x)s(x) 在 V4V_4 上的面积(阴影)是 S4=−0.14531S_4=−0.14531。下:精确通量 q∗q^* 在两个面上的值 Q3=0.66732Q_3=0.66732、Q4=0.52202Q_4=0.52202 之差等于这个面积;圆圈是收敛解的数值通量 H3=0.66252H_3=0.66252、H4=0.51721H_4=0.51721:它们与各自的 QQ 都相差 cH=−0.00481c_H=−0.00481(两个面上的差相同,第 5 节)。
Figure 9 · The balance of one dual volume (V_4, x[0.4375, 0.5625], default design). Top: the area of the source s(x) over V_4 (shaded) is S_4=−0.14531. Bottom: the difference of the exact flux q* at the two faces, Q_3=0.66732 and Q_4=0.52202, equals this area; the circles are the numerical fluxes of the converged solution, H_3=0.66252 and H_4=0.51721: each differs from its own Q by c_H=−0.00481, the same on both faces ().−1−0.500.5100.20.40.60.81xsS4​ = −0.14531V4​source s(x)0.30.40.50.60.70.800.20.40.60.81xqQ4​ − Q3​ = −0.14531exact flux q*numerical flux Hf​ (converged solution, N = 8)
Figure 9 · The balance of one dual volume (V4V_4, x∈[0.4375, 0.5625]x\in[0.4375,\,0.5625], default design). Top: the area of the source s(x)s(x) over V4V_4 (shaded) is S4=−0.14531S_4=−0.14531. Bottom: the difference of the exact flux q∗q^* at the two faces, Q3=0.66732Q_3=0.66732 and Q4=0.52202Q_4=0.52202, equals this area; the circles are the numerical fluxes of the converged solution, H3=0.66252H_3=0.66252 and H4=0.51721H_4=0.51721: each differs from its own QQ by cH=−0.00481c_H=−0.00481, the same on both faces (Section 5).

图里有一个值得记住的事实:收敛解的每个内部控制体都满足 Hj−Hj−1=Qj−Qj−1H_j-H_{j-1}=Q_j-Q_{j-1},所以通量误差 Hf−QfH_f-Q_f 在所有 NN 个面上是同一个常数 cHc_H(默认设置下 cH=−0.00481c_H=−0.00481,见第 5 节):平衡方程只确定通量的差,这个常数由两端的约束决定。精确节点值就不是这样(它们的面误差 ζf=Hf(u∗)−Qf\zeta_f=H_f(u^*)-Q_f 随面变化,见本节末尾的图 14)。

The figure shows a fact worth remembering: every interior dual volume of the converged solution satisfies Hj−Hj−1=Qj−Qj−1H_j-H_{j-1}=Q_j-Q_{j-1}, so the flux error Hf−QfH_f-Q_f is one and the same constant cHc_H on all NN faces (cH=−0.00481c_H=−0.00481 at the defaults, Section 5): the balance equations fix only the differences of the flux, and the constraints at the two ends decide the constant. The exact nodal values do not behave like this (their face errors ζf=Hf(u∗)−Qf\zeta_f=H_f(u^*)-Q_f change from face to face, see Figure 14 at the end of this section).

下面的面板对任意内部节点 jj 和当前设计重复这个计算:源项的积分、两个面上精确通量之差、数值通量,以及收敛解与精确节点值各自的残差。

The panel below repeats this computation for any interior node jj and the current design: the integral of the source, the difference of the exact flux at the two faces, the numerical fluxes, and the residuals of the converged solution and of the exact nodal values.

一个面上的数值通量:对流加黏性

The numerical flux on a face: convective plus viscous

面 ff 的通量分两部分,用不同的输入:对流部分用面两侧重构出的状态 qL,qRq_L,q_R(下面叫“迹”),黏性部分用两侧节点的未重构状态 UL=UfU_L=U_f、UR=Uf+1U_R=U_{f+1} 和它们之间的距离 dfd_f:

The flux of face ff has two parts that use different inputs: the convective part uses the states qL,qRq_L,q_R reconstructed on its two sides (called traces below) and the viscous part uses the raw states UL=UfU_L=U_f, UR=Uf+1U_R=U_{f+1} of the two nodes and the distance dfd_f between them:

Hf=14(qL2+qR2)−α2 (qR−qL)⏟Hc(qL,qR) − νdf (UR−UL)⏟Hv,α=2,df=h.H_f=\underbrace{\tfrac14\bigl(q_L^2+q_R^2\bigr)-\tfrac{\alpha}{2}\,(q_R-q_L)}_{H^c(q_L,q_R)}\ \underbrace{-\,\frac{\nu}{d_f}\,(U_R-U_L)}_{H^v},\qquad \alpha=2,\qquad d_f=h.

本页其他地方(包括本节开头的公式),qq 与 q∗q^* 表示总通量;面上的重构状态沿用其他一维页面的写法 qL,qRq_L,q_R。

Elsewhere on this page, including the first display of this section, qq and q∗q^* denote the total flux; for the face states the page follows the other 1-D pages and writes qL,qRq_L,q_R.

对流部分是 Rusanov 通量:两侧物理通量 F(u)=u2/2F(u)=u^2/2 的算术平均,减去与状态跳跃成比例的耗散。耗散项里的波速 α=2\alpha=2 取固定值,不随状态或设计变化,所以求导时没有隐藏的波速项(通常的波速 max⁡(∣qL∣,∣qR∣)\max(|q_L|,|q_R|) 在 ∣qL∣=∣qR∣|q_L|=|q_R| 处不可导,用它构成的 Rusanov 通量在 qL=−qR≠0q_L=-q_R\ne0 处不可导)。固定的 α=2\alpha=2 是否够大,要看迹的大小:在一次扫描里(N=8, 32, 128N=8,\,32,\,128、三种重构、a=−0.5, −0.25, 0.25, 0.5a=-0.5,\,-0.25,\,0.25,\,0.5、φ=0.07, 0.3, 0.55, 0.8\varphi=0.07,\,0.3,\,0.55,\,0.8、ν=0.001, 0.01, 0.1, 1\nu=0.001,\,0.01,\,0.1,\,1,共 576 个组合),571 个收敛,收敛的状态里迹都满足 ∣q∣<2|q|<2,最大的是 1.669;其余 5 个是 N=8N=8 上 ∣a∣=0.5|a|=0.5 的极端设计:页面的 Newton 迭代把状态限制在 0.1<U<1.90.1<U<1.9 内(第 5 节),没有收敛。去掉这个范围限制,从精确节点值出发(不行就换别的初始向量)的 Newton 迭代对这几个设计都找到了离散方程的解,最小值 Umin⁡U_{\min} 是:一阶 0.0919,光滑限制器(ν=0.001\nu=0.001 与 0.010.01)−1.180 与 −1.035,都在这个范围之外(页面那时会报告求解失败)。Rusanov 通量满足相容性 Hc(u,u)=F(u)H^c(u,u)=F(u),并且同一个 HfH_f 离开左边的控制体 VfV_f、进入右边的控制体 Vf+1V_{f+1},所以内部通量在全局求和中抵消。黏性部分是物理通量 −νux-\nu u_x 的中心差分近似,距离 df=hd_f=h 在每个面上都一样,两个边界面也不例外(格心页的边界面读给定值,距离是 h/2h/2)。

The convective part is the Rusanov flux: the mean of the physical fluxes F(u)=u2/2F(u)=u^2/2 of the two sides, minus a dissipation proportional to the jump of the state. The dissipation speed α=2\alpha=2 is a fixed number that depends on neither the state nor the design, so differentiation hides no wave-speed term (the usual wave speed max⁡(∣qL∣,∣qR∣)\max(|q_L|,|q_R|) is not differentiable where ∣qL∣=∣qR∣|q_L|=|q_R|, and the Rusanov flux built with it is not differentiable where qL=−qR≠0q_L=-q_R\ne0). Whether the fixed α=2\alpha=2 is large enough depends on the size of the traces: in a scan (N=8, 32, 128N=8,\,32,\,128, the three reconstructions, a=−0.5, −0.25, 0.25, 0.5a=-0.5,\,-0.25,\,0.25,\,0.5, φ=0.07, 0.3, 0.55, 0.8\varphi=0.07,\,0.3,\,0.55,\,0.8, ν=0.001, 0.01, 0.1, 1\nu=0.001,\,0.01,\,0.1,\,1: 576 combinations) 571 converged, and in every converged state the traces satisfy ∣q∣<2|q|<2, the largest being 1.669; the other 5 are extreme designs with ∣a∣=0.5|a|=0.5 on N=8N=8 for which the page's Newton iteration, which keeps the state inside 0.1<U<1.90.1<U<1.9 (Section 5), did not converge. Without that box a Newton iteration, started from the exact nodal values or, where that fails, from other starting vectors, finds a solution of the discrete equations for each of them, with the smallest value Umin⁡U_{\min} equal to 0.0919 at first order and −1.180 and −1.035 with the smooth limiter (ν=0.001\nu=0.001 and 0.010.01), outside the box in every case (the page then reports a failed solve). The flux is consistent, Hc(u,u)=F(u)H^c(u,u)=F(u), and the same HfH_f leaves the volume VfV_f on the left and enters the volume Vf+1V_{f+1} on the right, so the interior fluxes cancel in a global sum. The viscous part is the central-difference approximation of the physical flux −νux-\nu u_x, with the distance df=hd_f=h on every face, the two boundary faces included (on the cell-centred page a boundary face reads a prescribed value at the distance h/2h/2).

耗散的真面目:精确恒等式

What the dissipation really is: exact identities

耗散项 −(α/2)(qR−qL)-(\alpha/2)(q_R-q_L) 是人工黏性,它的作用可以写成精确的恒等式(下面的面板在当前状态上再验算一遍)。一阶时迹等于节点值,内部行 jj 的通量差 Hj−Hj−1=Rj+SjH_j-H_{j-1}=R_j+S_j 是

The dissipation term −(α/2)(qR−qL)-(\alpha/2)(q_R-q_L) is artificial viscosity, and what it does can be written as exact identities (the panel below checks them again on the current state). At first order the traces equal the nodal values and the flux difference of an interior row jj, Hj−Hj−1=Rj+SjH_j-H_{j-1}=R_j+S_j, is

Rj+Sj=14(Uj+12−Uj−12)−(1+νh)(Uj+1−2Uj+Uj−1),1≤j≤N−1.R_j+S_j=\tfrac14\bigl(U_{j+1}^2-U_{j-1}^2\bigr)-\Bigl(1+\frac{\nu}{h}\Bigr)\bigl(U_{j+1}-2U_j+U_{j-1}\bigr),\qquad 1\le j\le N-1.

这正是物理黏性 ν\nu 再加人工黏性 hh 的中心格式(除以 hh 后是 u ux−(ν+h) uxxu\,u_x-(\nu+h)\,u_{xx} 的中心差分):一阶格式在全部 N−1N-1 个内部行上就是黏性 ν+h\nu+h 的中心格式,紧邻边界的第 11 行与第 N−1N-1 行也不例外,因为边界节点的值 U0,UNU_0,U_N 就是向量里的普通分量(格心页的第一行与最后一行读给定值、距离 h/2h/2,不是这个形式)。默认 N=8N=8 时 h=0.125h=0.125,是 ν=0.01\nu=0.01 的 12.5 倍,等价地 h/ν=Peh/uinh/\nu=\mathrm{Pe}_h/u_{\rm in},网格 Péclet 数 Peh=uinh/ν=11.4\mathrm{Pe}_h=u_{\rm in}h/\nu=11.4;hh 要小到与 ν\nu 同量级(这里 N≈100N\approx100),人工黏性才不再主导。无限制器线性重构时,在两侧节点都做了重构的面上(1≤f≤N−21\le f\le N-2),耗散项是三阶差分:

This is exactly the central scheme for the physical viscosity ν\nu plus an artificial viscosity hh (divided by hh it is the central difference of u ux−(ν+h) uxxu\,u_x-(\nu+h)\,u_{xx}): on all N−1N-1 interior rows the first-order scheme is the central scheme for the viscosity ν+h\nu+h, the first row 11 and the last row N−1N-1 included, because the boundary values U0,UNU_0,U_N are ordinary entries of the vector (on the cell-centred page the first and the last row read a prescribed value at the distance h/2h/2 and do not have this form). At the default N=8N=8 one has h=0.125h=0.125, that is 12.5 times ν=0.01\nu=0.01; equivalently h/ν=Peh/uinh/\nu=\mathrm{Pe}_h/u_{\rm in} with the mesh Péclet number Peh=uinh/ν=11.4\mathrm{Pe}_h=u_{\rm in}h/\nu=11.4; hh has to become comparable with ν\nu (about N≈100N\approx100 here) before the artificial viscosity stops dominating. With unlimited linear reconstruction, on a face whose two nodes are both reconstructed (1≤f≤N−21\le f\le N-2) the dissipation of the face is a third difference:

−(qR−qL)=14(Uf+2−3Uf+1+3Uf−Uf−1),1≤f≤N−2,-(q_R-q_L)=\tfrac14\bigl(U_{f+2}-3U_{f+1}+3U_f-U_{f-1}\bigr),\qquad 1\le f\le N-2,

行 jj(2≤j≤N−22\le j\le N-2,即两个这样的面之差)的耗散是四阶差分,对光滑数据是 O(h4)O(h^4):

and that of a row 2≤j≤N−22\le j\le N-2 (the difference of two such faces) is a fourth difference, O(h4)O(h^4) for smooth data:

14(Uj+2−4Uj+1+6Uj−4Uj−1+Uj−2)=O(h4).\tfrac14\bigl(U_{j+2}-4U_{j+1}+6U_j-4U_{j-1}+U_{j-2}\bigr)=O(h^4).

两个边界面不同:边界节点用单侧斜率,qL(0)=12(U0+U1)q_L(0)=\tfrac12(U_0+U_1) 而 qR(0)=14U0+U1−14U2q_R(0)=\tfrac14U_0+U_1-\tfrac14U_2(最后一个面对称),所以它们的耗散是二阶差分,对光滑数据是 O(h2)O(h^2):

The two boundary faces are different: the boundary node uses a one-sided slope, qL(0)=12(U0+U1)q_L(0)=\tfrac12(U_0+U_1) and qR(0)=14U0+U1−14U2q_R(0)=\tfrac14U_0+U_1-\tfrac14U_2 (the last face is symmetric), so their dissipation is a second difference, O(h2)O(h^2) for smooth data:

−(qR−qL)∣f=0=14(U0−2U1+U2),−(qR−qL)∣f=N−1=−14(UN−2−2UN−1+UN).-(q_R-q_L)\Big|_{f=0}=\tfrac14\bigl(U_0-2U_1+U_2\bigr),\qquad -(q_R-q_L)\Big|_{f=N-1}=-\tfrac14\bigl(U_{N-2}-2U_{N-1}+U_N\bigr).

于是第 11 行与第 N−1N-1 行的耗散是 14(U3−4U2+5U1−2U0)\tfrac14(U_3-4U_2+5U_1-2U_0) 与 14(UN−3−4UN−2+5UN−1−2UN)\tfrac14(U_{N-3}-4U_{N-2}+5U_{N-1}-2U_N),对光滑数据约为 −h24uxx-\tfrac{h^2}{4}u_{xx},除以 hh 后相当于只在这两行加了人工黏性 h/4h/4(一阶格式在每一行都是 hh);其余各行只有四阶的超黏性。光滑限制器时权重随状态变化,没有这样的闭式。(上面每个恒等式都在随机状态和设计上用模型验算过,面板在当前解上再验算一遍。)

So the dissipation of the first row 11 and the last row N−1N-1 is 14(U3−4U2+5U1−2U0)\tfrac14(U_3-4U_2+5U_1-2U_0) and 14(UN−3−4UN−2+5UN−1−2UN)\tfrac14(U_{N-3}-4U_{N-2}+5U_{N-1}-2U_N), about −h24uxx-\tfrac{h^2}{4}u_{xx} for smooth data, which after division by hh is an artificial viscosity h/4h/4 acting on these two rows only (the first-order scheme has hh on every row); all other rows have only a fourth-order hyperviscosity. With the smooth limiter the weights change with the state and there is no such closed form. (Each identity above was checked with the model on random states and designs, and the panel checks it once more on the current solution.)

格心页的端单元不重构,面 0,1,N−1,N0,1,N-1,N 上有一个迹是单元平均值,耗散约为 −h2ux-\tfrac h2u_x,相当于 h/2h/2 的人工黏性,是一阶量。本页没有这样的面:边界节点的单侧斜率只有一阶精度,但它只乘外推距离 h/2h/2——qL(0)=12(U0+U1)q_L(0)=\tfrac12(U_0+U_1) 是线性插值,在 x1/2x_{1/2} 处的误差是 h28∣uxx∣\tfrac{h^2}{8}|u_{xx}|——所以边界面的迹同样是二阶精确的,面上的跳跃只有 O(h2)O(h^2)。图 10 在精确节点值与精确单元平均值上量出跳跃 ∣qR−qL∣|q_R-q_L|,以一阶跳跃 h∣ux∣h|u_x| 为单位:无限制器线性重构时,本页的边界面随 NN 加倍缩小到约一半(N=64N=64 时 0.0142,N=1024N=1024 时 0.0007),格心页的边界面趋于 12\tfrac12(0.507 与 0.500);内部面两页都是 O(h2)O(h^2)。光滑限制器的情形见下面。

The cell-centred page does not reconstruct its end cells: on faces 0,1,N−1,N0,1,N-1,N one trace is a cell mean and the dissipation is about −h2ux-\tfrac h2u_x, an artificial viscosity h/2h/2 and a first-order quantity. This page has no such face: the one-sided slope of a boundary node is only first-order accurate, but it is multiplied by the extrapolation distance h/2h/2 only, qL(0)=12(U0+U1)q_L(0)=\tfrac12(U_0+U_1) is a linear interpolation whose error at x1/2x_{1/2} is h28∣uxx∣\tfrac{h^2}{8}|u_{xx}|, so the trace of a boundary face is second-order accurate too, and the jump across it is only O(h2)O(h^2). Figure 10 measures the jump ∣qR−qL∣|q_R-q_L| on the exact nodal values and on the exact cell means, in units of the first-order jump h∣ux∣h|u_x|: with unlimited linear reconstruction the boundary faces of this page shrink to about half when NN doubles (0.0142 at N=64N=64 and 0.0007 at N=1024N=1024), those of the cell-centred page tend to 12\tfrac12 (0.507 and 0.500); on the interior faces both pages are O(h2)O(h^2). The smooth limiter is discussed below.

图 10 · 面上的跳跃 |q_R-q_L|/(h|u_x|)(精确数据,默认设计,不解方程)。(a) 两个边界面中较大的一个:本页无限制器线性重构(蓝)按 h 趋于零,格心页(紫虚线)趋于 1/2;本页光滑限制器(红)在细网格上也趋于 1/2(N=4096 时 0.4992),因为边界节点的单侧斜率不被限制,而内部的斜率被关掉了。(b) 内部面:一阶(灰)是 1,无限制器线性按 h^2 趋于零,光滑限制器在细网格上趋于 1(N=4096 时 0.9986)。(a) 两个边界面中较大的一个10-4​10-3​10-2​10-1​18321285122048N跳跃 / (h |ux​|)(b) 内部面(|ux​| 较大处的中位数)10-7​10-6​10-5​10-4​10-3​10-2​10-1​18321285122048N跳跃 / (h |ux​|)格点 一阶格点 无限制器线性格点 光滑限制器格心 无限制器线性
图 10 · 面上的跳跃 ∣qR−qL∣/(h∣ux∣)|q_R-q_L|/(h|u_x|)(精确数据,默认设计,不解方程)。(a) 两个边界面中较大的一个:本页无限制器线性重构(蓝)按 hh 趋于零,格心页(紫虚线)趋于 12\tfrac12;本页光滑限制器(红)在细网格上也趋于 12\tfrac12(N=4096N=4096 时 0.4992),因为边界节点的单侧斜率不被限制,而内部的斜率被关掉了。(b) 内部面:一阶(灰)是 1,无限制器线性按 h2h^2 趋于零,光滑限制器在细网格上趋于 1(N=4096N=4096 时 0.9986)。
Figure 10 · The jump across a face, |q_R-q_L|/(h|u_x|) (exact data, default design, no solve). (a) The larger of the two boundary faces: with unlimited linear reconstruction this page (blue) tends to zero like h, the cell-centred page (violet, dashed) tends to 1/2; this page's smooth limiter (red) also tends to 1/2 on fine meshes (0.4992 at N=4096), because the one-sided slope of a boundary node is not limited while the interior slopes are switched off. (b) Interior faces: first order (grey) is 1, unlimited linear tends to zero like h^2, the smooth limiter tends to 1 on fine meshes (0.9986 at N=4096).(a) the larger of the two boundary faces10-4​10-3​10-2​10-1​18321285122048Njump / (h |ux​|)(b) interior faces (median where |ux​| is large)10-7​10-6​10-5​10-4​10-3​10-2​10-1​18321285122048Njump / (h |ux​|)node first ordernode unlimited linearnode smooth limitercell-centred unlimited linear
Figure 10 · The jump across a face, ∣qR−qL∣/(h∣ux∣)|q_R-q_L|/(h|u_x|) (exact data, default design, no solve). (a) The larger of the two boundary faces: with unlimited linear reconstruction this page (blue) tends to zero like hh, the cell-centred page (violet, dashed) tends to 12\tfrac12; this page's smooth limiter (red) also tends to 12\tfrac12 on fine meshes (0.4992 at N=4096N=4096), because the one-sided slope of a boundary node is not limited while the interior slopes are switched off. (b) Interior faces: first order (grey) is 1, unlimited linear tends to zero like h2h^2, the smooth limiter tends to 1 on fine meshes (0.9986 at N=4096N=4096).

网格能分辨黏性尺度吗?

Does the mesh resolve the viscous scale?

第 1 节说过,伴随在入口 x=0x=0 有一个宽 ν/u\nu/u 的层。网格 Péclet 数 Peh=u h/ν\mathrm{Pe}_h=u\,h/\nu 就是网格间距与这个宽度之比。默认设计下层宽 ν/uin=0.0109\nu/u_{\rm in}=0.0109,而 N=8N=8 的间距是 0.125,Peh=11.4\mathrm{Pe}_h=11.4:第一个内部节点远在层外。Peh<1\mathrm{Pe}_h<1 要 N≥92N\ge92,页面的网格里只有 N=128N=128 做到;层里至少有 3 个间距(h≤ν/(3uin)h\le\nu/(3u_{\rm in}))要 N≥275N\ge275,页面上没有这样的网格。ν=0.1\nu=0.1 时 N≥10N\ge10 就够 Peh<1\mathrm{Pe}_h<1。下面的面板让你换 NN 和 ν\nu,比较网格间距与层宽:

Section 1 said that the adjoint has a layer of width ν/u\nu/u at the inlet x=0x=0. The mesh Péclet number Peh=u h/ν\mathrm{Pe}_h=u\,h/\nu is the mesh spacing divided by this width. At the default design the layer width is ν/uin=0.0109\nu/u_{\rm in}=0.0109 while the spacing of N=8N=8 is 0.125 and Peh=11.4\mathrm{Pe}_h=11.4: the first interior node is far outside the layer. Peh<1\mathrm{Pe}_h<1 needs N≥92N\ge92, and among the meshes of the page only N=128N=128 achieves it; at least 3 intervals inside the layer (h≤ν/(3uin)h\le\nu/(3u_{\rm in})) need N≥275N\ge275, which the page does not offer. For ν=0.1\nu=0.1, N≥10N\ge10 is enough for Peh<1\mathrm{Pe}_h<1. The panel below lets you change NN and ν\nu and compare the mesh spacing with the layer width:

重构:从节点值到面上的状态

Reconstruction: from nodal values to face states

每个节点用一个斜率 σj\sigma_j 把自己的值重构成一条线段,线段在它的对偶控制体两端的值就是相邻面的迹。斜率由两个单侧差 lj=Uj−Uj−1l_j=U_j-U_{j-1}、rj=Uj+1−Ujr_j=U_{j+1}-U_j 决定(σj\sigma_j 是跨过一个间距的变化量,不除以 hh)。两个边界节点只有一个邻居,用单侧差,限制器只在两侧邻居都在的节点上起作用:

Each node is reconstructed as a line segment with one slope σj\sigma_j, and the values of the segment at the two ends of its dual volume are the traces of the neighbouring faces. The slope is determined by the two one-sided differences lj=Uj−Uj−1l_j=U_j-U_{j-1} and rj=Uj+1−Ujr_j=U_{j+1}-U_j (σj\sigma_j is the change across one spacing, not divided by hh). A boundary node has only one neighbour and uses the one-sided difference; the limiter acts only on nodes that have both neighbours:

σj={0(𝚏𝚒𝚛𝚜𝚝),lj+rj2(𝚗𝚘𝚗𝚎),lj rj (lj+rj)lj2+rj2+ϵ2(𝚜𝚖𝚘𝚘𝚝𝚑), ϵ=0.01,1≤j≤N−1;σ0={0r0r0,  σN={0lNlN  (𝚏𝚒𝚛𝚜𝚝,𝚗𝚘𝚗𝚎,𝚜𝚖𝚘𝚘𝚝𝚑),\sigma_j=\begin{cases}0&(\mathtt{first}),\\[2pt] \dfrac{l_j+r_j}2&(\mathtt{none}),\\[6pt] \dfrac{l_j\,r_j\,(l_j+r_j)}{l_j^2+r_j^2+\epsilon^2}&(\mathtt{smooth}),\ \epsilon=0.01,\end{cases}\quad 1\le j\le N-1;\qquad \sigma_0=\begin{cases}0\\ r_0\\ r_0\end{cases},\ \ \sigma_N=\begin{cases}0\\ l_N\\ l_N\end{cases}\ \ (\mathtt{first},\mathtt{none},\mathtt{smooth}),
qL(f)=Uf+12σf,qR(f)=Uf+1−12σf+1,f=0,…,N−1.q_L(f)=U_f+\tfrac12\sigma_f,\qquad q_R(f)=U_{f+1}-\tfrac12\sigma_{f+1},\qquad f=0,\dots,N-1.

公式中的 first、none、smooth 是三种重构在代码里的名字,分别对应控制面板中的“一阶”“无限制器线性(二阶)”“光滑限制器”。“none”是无限制器的中心斜率,二阶精度,但不保证单调。边界节点的斜率 r0=U1−U0r_0=U_1-U_0 只是一阶精确的,但它只乘外推距离 h/2h/2:qL(0)=U0+12r0=12(U0+U1)q_L(0)=U_0+\tfrac12r_0=\tfrac12(U_0+U_1) 在 x1/2x_{1/2} 处的误差是 O(h2)O(h^2),所以边界面的迹和内部面的迹一样是二阶精确的(格心页的端单元不重构,迹只有一阶精度)。

In the formula, “first”, “none” and “smooth” are the code names of the three reconstructions (First order, Unlimited linear (second order) and Smooth limiter in the control panel). The slope “none” is the unlimited central slope: second-order accurate but not monotone. The slope r0=U1−U0r_0=U_1-U_0 of a boundary node is only first-order accurate, but it is multiplied by the extrapolation distance h/2h/2 only: qL(0)=U0+12r0=12(U0+U1)q_L(0)=U_0+\tfrac12r_0=\tfrac12(U_0+U_1) has an error O(h2)O(h^2) at x1/2x_{1/2}, so the traces of the boundary faces are second-order accurate like those of the interior faces (the end cells of the cell-centred page are not reconstructed and their traces are only first-order accurate).

无限制器线性重构时,迹是未知量的固定线性组合:内部面 1≤f≤N−21\le f\le N-2 上 qL=−14Uf−1+Uf+14Uf+1q_L=-\tfrac14U_{f-1}+U_f+\tfrac14U_{f+1}、qR=14Uf+Uf+1−14Uf+2q_R=\tfrac14U_f+U_{f+1}-\tfrac14U_{f+2};两个边界面一侧是 qL(0)=12U0+12U1q_L(0)=\tfrac12U_0+\tfrac12U_1、qR(N−1)=12UN−1+12UNq_R(N-1)=\tfrac12U_{N-1}+\tfrac12U_N,另一侧与内部面同形。所以一个内部面依赖 4 个未知量,紧邻边界的面 00 与 N−1N-1 依赖 3 个(U0,U1,U2U_0,U_1,U_2 与 UN−2,UN−1,UNU_{N-2},U_{N-1},U_N),一阶时每个面只依赖 2 个。一个内部节点的残差行用面 j−1j-1 与面 jj:涉及 Uj−2,…,Uj+2U_{j-2},\dots,U_{j+2} 共 5 个未知量,第 11 行与第 N−1N-1 行是 4 个(一阶是 3 个),第 00 行与第 NN 行是约束,只含自己。默认网格上由页面的前向代码量出(N=8N=8):无限制器线性每个面依赖 3、4、4、4、4、4、4、3 个未知量,每行 1、4、5、5、5、5、5、4、1 个;一阶每个面 2、2、2、2、2、2、2、2,每行 1、3、3、3、3、3、3、3、1。光滑限制器时这些权重随状态变化,依赖的未知量相同。于是状态 Jacobian AA 有 5N−55N-5 个非零元(二阶,默认网格上 35 个),一阶有 3N−13N-1 个(23 个);独立的 Python 程序在 N=32N=32 到 6553665536 的各次运行里数出的非零元个数与这两个公式一致。

With unlimited linear reconstruction the traces are fixed linear combinations of the unknowns: on an interior face 1≤f≤N−21\le f\le N-2 one has qL=−14Uf−1+Uf+14Uf+1q_L=-\tfrac14U_{f-1}+U_f+\tfrac14U_{f+1} and qR=14Uf+Uf+1−14Uf+2q_R=\tfrac14U_f+U_{f+1}-\tfrac14U_{f+2}; on the two boundary faces one trace is qL(0)=12U0+12U1q_L(0)=\tfrac12U_0+\tfrac12U_1 and qR(N−1)=12UN−1+12UNq_R(N-1)=\tfrac12U_{N-1}+\tfrac12U_N and the other has the interior form. So an interior face depends on 4 unknowns, the faces 00 and N−1N-1 next to a boundary on 3 (U0,U1,U2U_0,U_1,U_2 and UN−2,UN−1,UNU_{N-2},U_{N-1},U_N), and at first order every face depends on only 2. The residual row of an interior node uses faces j−1j-1 and jj: it touches the 5 unknowns Uj−2,…,Uj+2U_{j-2},\dots,U_{j+2}, the first row 11 and the last row N−1N-1 touch 4 (3 at first order), and rows 00 and NN are constraints and contain only themselves. Measured with the page's tangent code on the default mesh (N=8N=8): with unlimited linear reconstruction the faces touch 3, 4, 4, 4, 4, 4, 4, 3 unknowns and the rows 1, 4, 5, 5, 5, 5, 5, 4, 1; at first order the faces 2, 2, 2, 2, 2, 2, 2, 2 and the rows 1, 3, 3, 3, 3, 3, 3, 3, 1. With the smooth limiter these weights change with the state and the unknowns touched are the same. So the state Jacobian AA has 5N−55N-5 nonzeros at second order (35 on the default mesh) and 3N−13N-1 at first order (23); the independent Python program counts the nonzeros of its runs from N=32N=32 to 6553665536 and finds these two formulas.

先让模板动起来:下面的计算器给定一个内部面两侧的四个节点值,同时算出三种重构的迹、通量和四个偏导。只动最左边的值,哪些量会变?

First see the stencil in action: given the four nodal values around an interior face, the calculator below computes the traces, the flux and the four partial derivatives of all three reconstructions at once. Move only the left-most value: what changes?

再用滑块看斜率:给定两个单侧差,三种重构在中间节点的控制体里画出什么线段,再看边界节点:

Then look at the slope with the sliders: given the two one-sided differences, what segment does each reconstruction draw in the dual volume of the middle node; then look at a boundary node:

光滑限制器:极值处与细网格上

The smooth limiter: at extrema and on fine meshes

把光滑斜率写成中心斜率乘一个因子 ϕj\phi_j(它不是设计的相位 φ\varphi):σj=lj+rj2 ϕj\sigma_j=\dfrac{l_j+r_j}2\,\phi_j,ϕj=2ljrjlj2+rj2+ϵ2\phi_j=\dfrac{2l_jr_j}{l_j^2+r_j^2+\epsilon^2},因子严格落在 (−1,1)(-1,1) 内(van Albada 型的光滑有理斜率,ϵ\epsilon 使它处处可微)。lj,rjl_j,r_j 同号、相近且远大于 ϵ\epsilon 时 ϕj\phi_j 接近 1,斜率回到中心斜率;有一个差分为零时 ϕj=0\phi_j=0;在极值处(ljrj<0l_jr_j<0)ϕj\phi_j 为负,斜率很小并且与中心斜率反向,而不是被截成零。本页不声称它具有 TVD 或保正性。默认设计的光滑解里(N=8N=8),节点 6 是一个局部极小:l=−0.0890l=−0.0890,r=0.0376r=0.0376,中心斜率 (l+r)/2=−0.0257(l+r)/2=−0.0257,光滑斜率 σ=0.0182\sigma=0.0182,因子 ϕ=−0.709\phi=−0.709。

Write the smooth slope as the central slope times a factor ϕj\phi_j (not the phase φ\varphi of the design): σj=lj+rj2 ϕj\sigma_j=\dfrac{l_j+r_j}2\,\phi_j with ϕj=2ljrjlj2+rj2+ϵ2\phi_j=\dfrac{2l_jr_j}{l_j^2+r_j^2+\epsilon^2}, a factor strictly inside (−1,1)(-1,1) (of van Albada type, smooth because of ϵ\epsilon). It is close to 1 when lj,rjl_j,r_j have the same sign, are close to each other and are much larger than ϵ\epsilon, so the slope returns to the central one; it is 0 when one difference vanishes; at an extremum (ljrj<0l_jr_j<0) it is negative, so the slope is small and points against the central slope instead of being cut to zero. The page claims no TVD or positivity property for it. In the smooth solution of the default design (N=8N=8) node 6 is a local minimum: l=−0.0890l=−0.0890, r=0.0376r=0.0376, the central slope is (l+r)/2=−0.0257(l+r)/2=−0.0257, the smooth slope σ=0.0182\sigma=0.0182 and the factor ϕ=−0.709\phi=−0.709.

ϵ=0.01\epsilon=0.01 是固定的,而 lj,rj≈h uxl_j,r_j\approx h\,u_x 随 hh 缩小,所以网格细到 h ∣ux∣≪ϵh\,|u_x|\ll\epsilon 时因子远小于 1,重构几乎被关掉(h ∣ux∣=ϵh\,|u_x|=\epsilon 时因子仍是 23\tfrac23,h ∣ux∣=ϵ/2h\,|u_x|=\epsilon/\sqrt2 时是 12\tfrac12)。在精确节点值上,斜率最陡的节点处 ϕ≈1/(1+ϵ2/(2h2ux2))\phi\approx1/\bigl(1+\epsilon^2/(2h^2u_x^2)\bigr),降到 12\tfrac12 的网格是 N=2max⁡∣ux∣/ϵ≈178N=\sqrt2\max|u_x|/\epsilon\approx178(图 11):N=64N=64 时因子最大值是 0.885,N=128N=128(全局控件的最细网格)时是 0.658,N=1024N=1024 时只有 0.029,N=4096N=4096 时是 0.0019。因子一路下降,光滑限制器就一路变成一阶格式,状态误差跟着变:L1 误差在 N=32N=32 处停止下降(0.00254,一阶是 0.0382),此后一直在 0.0025 与 0.0031 之间,直到 N=256N=256(N=256N=256 时 0.00286),然后像一阶格式那样重新下降,到 N=16384N=16384 时与一阶格式只差 0.31%(图 11c)。边界节点不受限制器影响,所以细网格上边界面的跳跃趋于一阶跳跃的一半,而紧邻它的面已经是一阶的(图 10);这对误差阶的影响由第 15 节测量。

ϵ=0.01\epsilon=0.01 is fixed while lj,rj≈h uxl_j,r_j\approx h\,u_x shrink with hh, so when the mesh is fine enough that h ∣ux∣≪ϵh\,|u_x|\ll\epsilon the factor is far below 1 and the reconstruction is almost switched off (the factor is still 23\tfrac23 at h ∣ux∣=ϵh\,|u_x|=\epsilon and 12\tfrac12 at h ∣ux∣=ϵ/2h\,|u_x|=\epsilon/\sqrt2). On the exact nodal values, at the node of the steepest slope ϕ≈1/(1+ϵ2/(2h2ux2))\phi\approx1/\bigl(1+\epsilon^2/(2h^2u_x^2)\bigr), and the mesh at which this falls to 12\tfrac12 is N=2max⁡∣ux∣/ϵ≈178N=\sqrt2\max|u_x|/\epsilon\approx178 (Figure 11): the largest factor is 0.885 at N=64N=64, 0.658 at N=128N=128 (the finest mesh of the global controls), only 0.029 at N=1024N=1024 and 0.0019 at N=4096N=4096. As the factor falls, the smooth limiter degenerates to the first-order scheme, and its state error turns with it: the L1 error stops decreasing at N=32N=32 (0.00254, against 0.0382 at first order), then stays between 0.0025 and 0.0031 up to N=256N=256 (0.00286 at N=256N=256) and then falls again like the first-order error, from which it differs by only 0.31% at N=16384N=16384 (Figure 11c). The boundary nodes are not touched by the limiter, so on fine meshes the jump across a boundary face tends to half the first-order jump while the face next to it is already first order (Figure 10); what this does to the orders of the errors is measured in Section 15.

图 11 · 光滑限制器的因子 φ_j(精确节点值,默认设计)。(a) 沿 x:N=16 时在两个极值附近出现负值,网格越细曲线越低。(b) 因子的最大值与中位数随 N 衰减;虚线标出 N ≈ 178 与 φ=1/2。(c) 三种重构的状态 L1 误差(ν=0.01;N ≥ 32 是独立的 Python 实测,更粗的网格是本页模型):光滑限制器(红)先下降,在 N=32 处停止,平一段后沿着一阶曲线(灰)下降。(a) 精确节点值上的因子(|ϕ| < 1)−0.500.5100.20.40.60.81x因子 ϕj​N = 16N = 64N = 256N = 1024(b) 因子随 N 衰减00.20.40.60.81864512409632768N因子 ϕj​ 的最大值与中位数N ≈ 178最大值中位数(c) 状态 L1 误差:光滑限制器在细网格上并入一阶曲线10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​183212851220488192N状态 L1 误差一阶无限制器线性光滑限制器
图 11 · 光滑限制器的因子 ϕj\phi_j(精确节点值,默认设计)。(a) 沿 xx:N=16N=16 时在两个极值附近出现负值,网格越细曲线越低。(b) 因子的最大值与中位数随 NN 衰减;虚线标出 N≈178N\approx178 与 ϕ=12\phi=\tfrac12。(c) 三种重构的状态 L1 误差(ν=0.01\nu=0.01;N≥32N\ge32 是独立的 Python 实测,更粗的网格是本页模型):光滑限制器(红)先下降,在 N=32N=32 处停止,平一段后沿着一阶曲线(灰)下降。
Figure 11 · The factor φ_j of the smooth limiter (exact nodal values, default design). (a) Along x: at N=16 negative values occur near the two extrema, and the finer the mesh the lower the curve. (b) The maximum and the median of the factor decay with N; the dashed lines mark N ≈ 178 and φ=1/2. (c) The state L1 errors of the three reconstructions (ν=0.01; N ≥ 32 independent Python runs, the coarser meshes this page's model): the smooth limiter (red) first falls, stops at N=32, stays level for a while and then follows the first-order curve (grey) down.(a) the factor on exact nodal values (|ϕ| < 1)−0.500.5100.20.40.60.81xfactor ϕj​N = 16N = 64N = 256N = 1024(b) the factor decays with N00.20.40.60.81864512409632768Nmaximum and median of ϕj​N ≈ 178maximummedian(c) state L1 error: on fine meshes the smooth limiter joins the first-order curve10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​183212851220488192Nstate L1 errorfirst orderunlimited linearsmooth limiter
Figure 11 · The factor ϕj\phi_j of the smooth limiter (exact nodal values, default design). (a) Along xx: at N=16N=16 negative values occur near the two extrema, and the finer the mesh the lower the curve. (b) The maximum and the median of the factor decay with NN; the dashed lines mark N≈178N\approx178 and ϕ=12\phi=\tfrac12. (c) The state L1 errors of the three reconstructions (ν=0.01\nu=0.01; N≥32N\ge32 independent Python runs, the coarser meshes this page's model): the smooth limiter (red) first falls, stops at N=32N=32, stays level for a while and then follows the first-order curve (grey) down.

一个面的计算

The computation of one face

图 12 · 一个内部面(面 f=4,在 x=0.5625,节点 4 与 5 之间,默认设计的收敛解,无限制器线性重构)。四个节点的值(点)、各自在对偶控制体里的线性重构(实线)、面上的两个迹 q_L、q_R,以及用它们算出的对流、黏性与总通量;点线是两个未重构状态的割线。节点 3U3​ = 1.1656σ3​ = −0.0567节点 4U4​ = 1.0574σ4​ = −0.1263节点 5U5​ = 0.9129σ5​ = −0.1178节点 6U6​ = 0.8218σ6​ = −0.0401面 f = 4(x = 0.5625,在节点 4 与 5 之间)qL​ = 0.9942qR​ = 0.9718点:节点值(黏性通量用);点线:它们的割线实线:各节点在自己的对偶控制体里的线性重构,端点是迹(对流通量用)对流 Hc​ = ¼(qL​² + qR​²) − (qR​ − qL​) = 0.50565黏性 Hv​ = −κf​ (UR​ − UL​) = −0.080 × (0.91290 − 1.05739) = 0.01156Hf​ = Hc​ + Hv​ = 0.51721
图 12 · 一个内部面(面 f=4f=4,在 x=0.5625x=0.5625,节点 44 与 55 之间,默认设计的收敛解,无限制器线性重构)。四个节点的值(点)、各自在对偶控制体里的线性重构(实线)、面上的两个迹 qLq_L、qRq_R,以及用它们算出的对流、黏性与总通量;点线是两个未重构状态的割线。
Figure 12 · One interior face (face f=4, at x=0.5625 between nodes 4 and 5, converged solution of the default design, unlimited linear reconstruction). The values of the four nodes (dots), their linear reconstructions across the dual volumes (solid), the two traces q_L, q_R at the face, and the convective, viscous and total flux computed from them; the dotted line is the secant of the two raw states.node 3U3​ = 1.1656σ3​ = −0.0567node 4U4​ = 1.0574σ4​ = −0.1263node 5U5​ = 0.9129σ5​ = −0.1178node 6U6​ = 0.8218σ6​ = −0.0401face f = 4 (x = 0.5625, between nodes 4 and 5)qL​ = 0.9942qR​ = 0.9718dots: nodal values (viscous flux); dotted: the secant through the two raw statessolid: the linear reconstruction of each node across its dual volume, whose end points are the traces (convective flux)convective Hc​ = ¼(qL​² + qR​²) − (qR​ − qL​) = 0.50565viscous Hv​ = −κf​ (UR​ − UL​) = −0.080 × (0.91290 − 1.05739) = 0.01156Hf​ = Hc​ + Hv​ = 0.51721
Figure 12 · One interior face (face f=4f=4, at x=0.5625x=0.5625 between nodes 44 and 55, converged solution of the default design, unlimited linear reconstruction). The values of the four nodes (dots), their linear reconstructions across the dual volumes (solid), the two traces qLq_L, qRq_R at the face, and the convective, viscous and total flux computed from them; the dotted line is the secant of the two raw states.

下面的播放器把这个面的计算拆成七步,每一步写出当时的数值;这七步就是第 5 节、第 8 节里残差代码的语句 1a 至 3(取值与重构 1a–1c,通量 2,分发 3),只是把迹和通量的两个部分分开显示。按“播放”或用步进按钮,换面、换重构再看一遍;面 00 与面 N−1N-1 的分发只进一个控制体,因为两个端点控制体不装配。

The player below splits the computation of this face into seven steps and writes the numbers of each step; the seven steps are statements 1a to 3 of the residual code of Section 5 and Section 8 (gather and reconstruct 1a–1c, flux 2, scatter 3), with the traces and the two parts of the flux shown separately. Press Play or use the step buttons, and change the face and the reconstruction to see it again; the scatter of face 00 and face N−1N-1 enters one volume only, because the two end volumes are not assembled.

一个面上的局部导数

Local derivatives on one face

第 8、9 节的切线与伴随,在面上只用到三类局部导数:数值通量对迹的偏导、对未重构状态的偏导,以及迹对未知量的偏导(此外还有通量对设计 ν\nu 的偏导,以及边界值和精确通量对设计的偏导)。数值通量是多项式,逐项求导:

On a face, the tangent and the adjoint of Sections 8 and 9 use only three kinds of local derivative: those of the numerical flux with respect to the traces, those with respect to the raw states, and those of the traces with respect to the unknowns (plus the derivative of the flux with respect to the design ν\nu and those of the boundary values and the exact fluxes with respect to the design). The numerical flux is a polynomial, so it is differentiated term by term:

cL=∂H∂qL=qL2+1,cR=∂H∂qR=qR2−1,∂H∂UL=+κf,∂H∂UR=−κf,κf=νdf=νh,∂H∂ν=−UR−ULh.c_L=\frac{\partial H}{\partial q_L}=\frac{q_L}2+1,\qquad c_R=\frac{\partial H}{\partial q_R}=\frac{q_R}2-1,\qquad \frac{\partial H}{\partial U_L}=+\kappa_f,\quad\frac{\partial H}{\partial U_R}=-\kappa_f,\quad \kappa_f=\frac{\nu}{d_f}=\frac\nu h,\qquad \frac{\partial H}{\partial\nu}=-\frac{U_R-U_L}{h}.

有两个性质可以检验这些公式。相容性 Hc(u,u)=u2/2H^c(u,u)=u^2/2 沿 qL=qR=uq_L=q_R=u 求导,得 cL+cR=uc_L+c_R=u:两个偏导把波速分成上游和下游两份。当 ∣qL∣,∣qR∣<2|q_L|,|q_R|<2 时 cL>0>cRc_L>0>c_R:通量随左状态增加、随右状态减小。默认设计的各面上(无限制器线性)cLc_L 在 1.401 与 1.597 之间,cRc_R 在 −0.595 与 −0.403 之间。黏性偏导 ±κf\pm\kappa_f 是常数,在每个面上(边界面也一样)κf=ν/h=0.080\kappa_f=\nu/h=0.080。

Two properties check these formulas. Consistency Hc(u,u)=u2/2H^c(u,u)=u^2/2 differentiated along qL=qR=uq_L=q_R=u gives cL+cR=uc_L+c_R=u: the two partial derivatives split the wave speed into an upstream and a downstream share. For ∣qL∣,∣qR∣<2|q_L|,|q_R|<2 one has cL>0>cRc_L>0>c_R: the flux increases with the left state and decreases with the right one. On the faces of the default design (unlimited linear) cLc_L lies between 1.401 and 1.597 and cRc_R between −0.595 and −0.403. The viscous partials ±κf\pm\kappa_f are constants, κf=ν/h=0.080\kappa_f=\nu/h=0.080 on every face, the boundary faces included.

迹对未知量的导数由斜率的导数决定:qL=Uf+12σfq_L=U_f+\tfrac12\sigma_f 与 qR=Uf+1−12σf+1q_R=U_{f+1}-\tfrac12\sigma_{f+1}。内部节点的斜率只依赖 lj,rjl_j,r_j,偏导 σl=∂σj/∂lj\sigma_l=\partial\sigma_j/\partial l_j、σr=∂σj/∂rj\sigma_r=\partial\sigma_j/\partial r_j 是:一阶 (0,0)(0,0);无限制器线性 (12,12)(\tfrac12,\tfrac12),与状态无关;光滑限制器(记 num=l r (l+r)\mathrm{num}=l\,r\,(l+r),den=l2+r2+ϵ2\mathrm{den}=l^2+r^2+\epsilon^2):

The derivatives of the traces with respect to the unknowns follow from those of the slopes: qL=Uf+12σfq_L=U_f+\tfrac12\sigma_f and qR=Uf+1−12σf+1q_R=U_{f+1}-\tfrac12\sigma_{f+1}. The slope of an interior node depends on lj,rjl_j,r_j only, and its partial derivatives σl=∂σj/∂lj\sigma_l=\partial\sigma_j/\partial l_j, σr=∂σj/∂rj\sigma_r=\partial\sigma_j/\partial r_j are: (0,0)(0,0) at first order; (12,12)(\tfrac12,\tfrac12) with unlimited linear reconstruction, independent of the state; and with the smooth limiter (write num=l r (l+r)\mathrm{num}=l\,r\,(l+r), den=l2+r2+ϵ2\mathrm{den}=l^2+r^2+\epsilon^2):

σl=(2lr+r2) den−2l numden2,σr=(l2+2lr) den−2r numden2.\sigma_l=\frac{(2lr+r^2)\,\mathrm{den}-2l\,\mathrm{num}}{\mathrm{den}^2},\qquad \sigma_r=\frac{(l^2+2lr)\,\mathrm{den}-2r\,\mathrm{num}}{\mathrm{den}^2}.

边界节点的斜率是单侧差,导数是常数:∂σ0/∂U0=−1\partial\sigma_0/\partial U_0=-1、∂σ0/∂U1=+1\partial\sigma_0/\partial U_1=+1,∂σN/∂UN=+1\partial\sigma_N/\partial U_N=+1、∂σN/∂UN−1=−1\partial\sigma_N/\partial U_{N-1}=-1(无限制器线性与光滑限制器;一阶全为 0)。无限制器线性重构时迹的导数就是上面的固定权重;光滑限制器时它们随状态变化。图 13 左:cL,cRc_L,c_R 随状态变化,灰带是本页各面迹的范围;右:每个面的通量对每个未知量的导数 ∂Hf/∂Uj\partial H_f/\partial U_j,一阶时每个面涉及 2 个未知量,无限制器线性时内部面涉及 4 个、紧邻边界的面 3 个。

The slope of a boundary node is a one-sided difference and its derivatives are constants: ∂σ0/∂U0=−1\partial\sigma_0/\partial U_0=-1, ∂σ0/∂U1=+1\partial\sigma_0/\partial U_1=+1, ∂σN/∂UN=+1\partial\sigma_N/\partial U_N=+1, ∂σN/∂UN−1=−1\partial\sigma_N/\partial U_{N-1}=-1 (unlimited linear and smooth limiter; all 0 at first order). With unlimited linear reconstruction the derivatives of the traces are the fixed weights above; with the smooth limiter they change with the state. Figure 13 left: cL,cRc_L,c_R against the state, the grey band being the range of the traces of this page; right: the derivative of every face flux with respect to every unknown, ∂Hf/∂Uj\partial H_f/\partial U_j; a face touches 2 unknowns at first order, and with unlimited linear reconstruction an interior face 4 and a face next to a boundary 3.

图 13 · 一个面上的导数(默认设计)。左:q_L=q_R=u 时 c_L=u/2+1 与 c_R=u/2-1,虚线是它们的和 u,灰带是本页各面迹的范围。右:∂ H_f/∂ U_j(N 行面、N+1 列未知量),蓝正橙负;一阶(上)每个面涉及两个未知量,无限制器线性(下)涉及四个(紧邻边界的面三个)。−0.500.511.50.40.60.811.21.4面上的状态 u(qL​ = qR​ = u)cL​ = u/2 + 1cR​ = u/2 − 1cL​ + cR​ = u1.54−0.571.59−0.561.60−0.601.56−0.671.49−0.721.44−0.721.44−0.681.48−0.6201234567801234567一阶:∂Hf​/∂Uj​列 j(未知量)0.700.170.12−0.391.54−0.110.11−0.401.58−0.080.10−0.391.54−0.130.11−0.371.45−0.220.13−0.361.36−0.300.14−0.351.33−0.330.15−0.361.23−0.0001234567801234567无限制器线性:∂Hf​/∂Uj​
图 13 · 一个面上的导数(默认设计)。左:qL=qR=uq_L=q_R=u 时 cL=u/2+1c_L=u/2+1 与 cR=u/2−1c_R=u/2-1,虚线是它们的和 uu,灰带是本页各面迹的范围。右:∂Hf/∂Uj\partial H_f/\partial U_j(NN 行面、N+1N+1 列未知量),蓝正橙负;一阶(上)每个面涉及两个未知量,无限制器线性(下)涉及四个(紧邻边界的面三个)。
Figure 13 · Derivatives on one face (default design). Left: c_L=u/2+1 and c_R=u/2-1 for equal traces q_L=q_R=u, the dashed line is their sum u, the grey band is the range of the traces of this page. Right: ∂ H_f/∂ U_j (N face rows, N+1 unknown columns), blue positive and orange negative; at first order (top) a face touches two unknowns, with unlimited linear reconstruction (bottom) four (three next to a boundary).−0.500.511.50.40.60.811.21.4state u at the face (qL​ = qR​ = u)cL​ = u/2 + 1cR​ = u/2 − 1cL​ + cR​ = u1.54−0.571.59−0.561.60−0.601.56−0.671.49−0.721.44−0.721.44−0.681.48−0.6201234567801234567first order: ∂Hf​/∂Uj​column j (unknown)0.700.170.12−0.391.54−0.110.11−0.401.58−0.080.10−0.391.54−0.130.11−0.371.45−0.220.13−0.361.36−0.300.14−0.351.33−0.330.15−0.361.23−0.0001234567801234567unlimited linear: ∂Hf​/∂Uj​
Figure 13 · Derivatives on one face (default design). Left: cL=u/2+1c_L=u/2+1 and cR=u/2−1c_R=u/2-1 for equal traces qL=qR=uq_L=q_R=u, the dashed line is their sum uu, the grey band is the range of the traces of this page. Right: ∂Hf/∂Uj\partial H_f/\partial U_j (NN face rows, N+1N+1 unknown columns), blue positive and orange negative; at first order (top) a face touches two unknowns, with unlimited linear reconstruction (bottom) four (three next to a boundary).

一个面上的数值(面 f=4f=4,x=0.5625x=0.5625)

One face with the page's numbers (face f=4f=4, x=0.5625x=0.5625)

下表是三种重构各自的收敛解在同一个面上的量;每种重构的解不同,所以连未重构状态 UL,URU_L,U_R 也不同。验证:Hf=Hc+HvH_f=H^c+H^v,cL,cRc_L,c_R 由迹算出。

The table lists the quantities of the same face in the converged solution of each reconstruction; the solutions differ, so even the raw states UL,URU_L,U_R differ. Check: Hf=Hc+HvH_f=H^c+H^v, and cL,cRc_L,c_R follow from the traces.

量Quantity公式Formula一阶first order无限制器线性unlimited linear光滑限制器smooth limiter
qLq_LUf+12σfU_f+\tfrac12\sigma_f0.8133680.9942230.986457
qRq_RUf+1−12σf+1U_{f+1}-\tfrac12\sigma_{f+1}0.7163290.9717830.942295
UL, URU_L,\ U_RUf, Uf+1U_f,\ U_{f+1}0.81337, 0.716331.05739, 0.912901.05090, 0.88952
HcH^c14(qL2+qR2)−(qR−qL)\tfrac14(q_L^2+q_R^2)-(q_R-q_L)0.3907120.5056510.509416
HvH^v−κf(UR−UL)-\kappa_f(U_R-U_L)0.0077630.0115590.012911
HfH_fHc+HvH^c+H^v0.3984750.5172110.522326
cL, cRc_L,\ c_RqL/2+1, qR/2−1q_L/2+1,\ q_R/2-11.4067, −0.64181.4971, −0.51411.4932, −0.5289

注意一阶时两个迹等于节点值,对流部分的跳跃 qR−qL=UR−ULq_R-q_L=U_R-U_L 较大,人工黏性起作用;无限制器线性时跳跃小得多。换一个面、换一种重构试试:

Note that at first order the traces equal the nodal values, the jump qR−qL=UR−ULq_R-q_L=U_R-U_L of the convective part is larger and the artificial viscosity acts; with unlimited linear reconstruction the jump is much smaller. Try another position and another reconstruction:

面通量的相容性

The consistency of the face flux

把精确节点值代进面通量,得到的 ζf=Hf(u∗)−Qf\zeta_f=H_f(u^*)-Q_f 就是第 4 节的面误差(QfQ_f 是精确通量);一个控制体的残差是它两个面的面误差之差:Rj(u∗)=ζj−ζj−1R_j(u^*)=\zeta_j-\zeta_{j-1}(第 5 节)。无限制器线性重构时,所有 NN 个面上 ζf=O(h2)\zeta_f=O(h^2),两个边界面也一样:N=64N=64 时最大的面误差在内部面(1≤f≤N−21\le f\le N-2)上是 2.91×10−42.91\times10^{−4},在边界面 00、N−1N-1 上是 2.52×10−42.52\times10^{−4};从 N=512N=512 到 N=1024N=1024 的观测阶是 2.00 与 2.00。一阶时 ζf≈−h ux\zeta_f\approx-h\,u_x,是 O(h)O(h)(观测阶 1.00)。格心页的无限制器线性重构在内部面(2≤f≤N−22\le f\le N-2)上同样是二阶,但在两端的面 0,1,N−1,N0,1,N-1,N 上只有一阶(观测阶 1.00,N=64N=64 时这些面上的误差是 1.33×10−21.33\times10^{−2},是本页边界面误差的 53 倍)。

Put the exact nodal values into the face flux: ζf=Hf(u∗)−Qf\zeta_f=H_f(u^*)-Q_f is the face error of Section 4 (QfQ_f is the exact flux), and the residual of a volume is the difference of the face errors of its two faces, Rj(u∗)=ζj−ζj−1R_j(u^*)=\zeta_j-\zeta_{j-1} (Section 5). With unlimited linear reconstruction ζf=O(h2)\zeta_f=O(h^2) on all NN faces, the two boundary faces included: at N=64N=64 the largest face error is 2.91×10−42.91\times10^{−4} on the interior faces (1≤f≤N−21\le f\le N-2) and 2.52×10−42.52\times10^{−4} on the boundary faces 00, N−1N-1; the observed orders from N=512N=512 to N=1024N=1024 are 2.00 and 2.00. At first order ζf≈−h ux\zeta_f\approx-h\,u_x, which is O(h)O(h) (observed order 1.00). The unlimited linear reconstruction of the cell-centred page is second order on its interior faces (2≤f≤N−22\le f\le N-2) too, but only first order on its end faces 0,1,N−1,N0,1,N-1,N (observed order 1.00; at N=64N=64 the error on these faces is 1.33×10−21.33\times10^{−2}, 53 times that of the boundary faces of this page).

图 14 · 精确节点值上的面误差 ζ_f=H_f(u*)-Q_f(默认设计,不解方程;格心页用它的精确单元平均值)。(a) 最大面误差随 N 的变化,细虚线是 h 与 h^2 的斜率:本页无限制器线性(蓝)在所有面上都按 h^2,一阶(灰)按 h,格心页(紫)在两端的面上按 h。(b) 本页无限制器线性的 N^2ζ_f 沿 x:在所有面上(两端的面也一样)都保持 O(1),各条曲线随 N 趋于同一个极限。(a) 面误差随 N 的变化10-7​10-6​10-5​10-4​10-3​10-2​10-1​1832128512N最大面误差 max|ζf​|hh²(b) 格点格式:N² ζf​ 沿 x−2−10100.20.40.60.81xN² ζf​(无限制器线性)格点 无限制器线性:边界面 0、N−1格点 无限制器线性:内部面格点 一阶:所有面格心 无限制器线性:两端的面 0、1、N−1、N格心 无限制器线性:内部面N = 8N = 16N = 32N = 64
图 14 · 精确节点值上的面误差 ζf=Hf(u∗)−Qf\zeta_f=H_f(u^*)-Q_f(默认设计,不解方程;格心页用它的精确单元平均值)。(a) 最大面误差随 NN 的变化,细虚线是 hh 与 h2h^2 的斜率:本页无限制器线性(蓝)在所有面上都按 h2h^2,一阶(灰)按 hh,格心页(紫)在两端的面上按 hh。(b) 本页无限制器线性的 N2ζfN^2\zeta_f 沿 xx:在所有面上(两端的面也一样)都保持 O(1)O(1),各条曲线随 NN 趋于同一个极限。
Figure 14 · The face error ζ_f=H_f(u*)-Q_f on the exact nodal values (default design, no solve; the cell-centred page uses its exact cell means). (a) The largest face error against N, the thin dashed lines show the slopes of h and h^2: unlimited linear on this page (blue) falls like h^2 on all faces, first order (grey) like h, the cell-centred page (violet) like h on its end faces. (b) N^2ζ_f of unlimited linear on this page along x: it stays O(1) on all faces, the faces at the two ends included, and the curves approach a common limit as N grows.(a) the face error against N10-7​10-6​10-5​10-4​10-3​10-2​10-1​1832128512Nlargest face error max|ζf​|hh²(b) node scheme: N² ζf​ along x−2−10100.20.40.60.81xN² ζf​ (unlimited linear)node unlimited linear: boundary faces 0, N−1node unlimited linear: interior facesnode first order: all facescell-centred unlimited linear: faces 0, 1, N−1, Ncell-centred unlimited linear: interior facesN = 8N = 16N = 32N = 64
Figure 14 · The face error ζf=Hf(u∗)−Qf\zeta_f=H_f(u^*)-Q_f on the exact nodal values (default design, no solve; the cell-centred page uses its exact cell means). (a) The largest face error against NN, the thin dashed lines show the slopes of hh and h2h^2: unlimited linear on this page (blue) falls like h2h^2 on all faces, first order (grey) like hh, the cell-centred page (violet) like hh on its end faces. (b) N2ζfN^2\zeta_f of unlimited linear on this page along xx: it stays O(1)O(1) on all faces, the faces at the two ends included, and the curves approach a common limit as NN grows.

第 4 节写两个端点的约束行,第 5 节把面的计算写成残差代码。

Section 4 writes the two constraint rows at the ends; Section 5 writes the face computation as the residual code.

第 4 节Section 4

边界条件:约束行

Boundary conditions: the constraint rows

本节实验:边界节点的行不是通量平衡,而是约束。先预测:把精确节点值 u∗(xj)u^*(x_j) 代入残差,哪些行不为零?紧邻边界的行与内部行相差几阶 hh?这样整个解的精度阶会降低一阶吗?写下预测,再看图 20。

Experiment: The rows of the two boundary nodes are not flux balances but constraints. Predict first: when the exact nodal values u∗(xj)u^*(x_j) are put into the residual, which rows are not zero, and by how many powers of hh do the rows next to the boundary differ from the interior rows? Does the error of the whole solution then lose an order? Write your prediction down, then look at Figure 20.

第 3 节写出了一个面上的通量。格点格式里每个面的两侧都有节点,两个边界面也不例外,所以边界不需要新的通量公式。边界上改变的只有两件事:边界节点的两行变成约束,边界节点的斜率只能用单侧差分。本节说明这两个约束行对残差、对 AA 和对 RDR_D 做了什么,边界面读什么、有多准,以及为什么边界不会让解的精度降阶。格心页的两个边界面只有一阶精度,这里的边界面与内部面同阶;两种格式的差别在本节一一量出。

Section 3 wrote the flux of a face. On the node mesh every face has a node on each side, the two boundary faces included, so the boundary needs no new flux formula. Only two things change at the boundary: the rows of the two boundary nodes become constraints, and the slope of a boundary node can only be a one-sided difference. This section says what the two constraint rows do to the residual, to AA and to RDR_D, what the boundary faces read and how accurate they are, and why the boundary does not cost an order of accuracy of the solution. The two end faces of the cell-centred page are only first-order accurate; the boundary faces here are as accurate as the interior ones, and the section measures where the two schemes differ.

为什么两端各要一个值

Why each end needs a value

把定常方程 qx=sq_x=s 从 00 积到 xx:

Integrate the steady equation qx=sq_x=s from 00 to xx:

q(x)=q(0)+∫0xs dt=q(0)+q∗(x)−q∗(0),ν ux=12u2−q(x).q(x)=q(0)+\int_0^xs\,\mathrm dt=q(0)+q^*(x)-q^*(0),\qquad \nu\,u_x=\tfrac12u^2-q(x).

第一式说明通量只剩一个待定常数 q(0)q(0);第二式是 uu 的一阶常微分方程,又带来一个积分常数。两个常数要两个条件:u(0)=uinu(0)=u_{\rm in},u(1)=uoutu(1)=u_{\rm out}。没有黏性(ν=0\nu=0)时第二式变成代数关系 12u2=q(x)\tfrac12u^2=q(x),只剩常数 q(0)q(0),入口给一个值就够了——这就是无黏 Burgers 页面只给入口条件的原因。对构造解 u=u∗u=u^*,q(0)=q∗(0)q(0)=q^*(0),即 q=q∗q=q^*。第 5 节会看到,离散解满足同样形式的关系,只是多出一个常数。

The first relation says that the flux is fixed up to one constant, q(0)q(0); the second is a first-order ordinary differential equation for uu, which brings a second constant of integration. Two constants need two conditions: u(0)=uinu(0)=u_{\rm in} and u(1)=uoutu(1)=u_{\rm out}. Without viscosity (ν=0\nu=0) the second relation becomes the algebraic 12u2=q(x)\tfrac12u^2=q(x), only the constant q(0)q(0) is left, and one inlet value is enough: this is why the inviscid Burgers pages prescribe an inlet value only. For the manufactured solution u=u∗u=u^* one has q(0)=q∗(0)q(0)=q^*(0), that is q=q∗q=q^*. Section 5 shows that the discrete solution satisfies a relation of the same form, with an extra constant.

两个约束行

The two constraint rows

未知量向量有 N+1N+1 个分量,两个边界值 U0,UNU_0,U_N 也在其中。它们的行不是通量平衡,而是说“这个未知量就等于给定值”:

The vector of unknowns has N+1N+1 entries, the two boundary values U0U_0 and UNU_N included. Their rows are not flux balances; they say that the unknown is the prescribed value:

R0=U0−uin(D),RN=UN−uout(D)(残差代码的语句 5,第 5 节;单位比例)。R_0=U_0-u_{\rm in}(D),\qquad R_N=U_N-u_{\rm out}(D)\qquad\text{(残差代码的语句 5,第 5 节;单位比例)。}
R0=U0−uin(D),RN=UN−uout(D)(statement 5 of the residual code, Section 5; unit scaling).R_0=U_0-u_{\rm in}(D),\qquad R_N=U_N-u_{\rm out}(D)\qquad\text{(statement 5 of the residual code, Section 5; unit scaling).}

每个面把它的通量加到两侧的对偶控制体上,但两个半宽的边界控制体 V0,VNV_0,V_N 不装配(第 5 节的语句 3 跳过它们)。给边界控制体写通量平衡,只会算出穿过入口的通量,那是输出而不是约束;U0U_0 的值本来就已经给定。

A face adds its flux to the dual volumes on its two sides, but the two half-width boundary volumes V0,VNV_0,V_N are not assembled (statement 3 of Section 5 skips them). A flux balance for a boundary volume would only compute the flux through the inlet, an output rather than a constraint; the value of U0U_0 is already given.

约束行对 A=R𝐔A=R_{\mathbf U} 的作用很简单:第 00 行和第 NN 行是单位行,A00=ANN=1A_{00}=A_{NN}=1,其余元素全为零(图 15 左图的实线框)。所以 Newton 修正满足 ΔU0=−R0\Delta U_0=-R_0:第一步之后 U0=uinU_0=u_{\rm in} 精确成立,因为约束行是线性的;本页的初始猜测在两端已经精确(它取精确节点值),所以每一步的修正在两端都是零。边界节点仍然是内部行的邻居:二阶重构时 U0U_0 出现在第 1,21,2 行,UNU_N 出现在第 N−2,N−1N-2,N-1 行(图 15 的虚线框;一阶重构时 U0U_0 只出现在第 11 行,UNU_N 只出现在第 N−1N-1 行),它们是 AA 的“边界列”。第 6 节会证明,AA 因此是分块三角的,det⁡A=det⁡AII\det A=\det A_{\rm II},其中 AIIA_{\rm II} 是去掉两个约束行和两个边界列后的内部块。

The effect on A=R𝐔A=R_{\mathbf U} is simple: rows 00 and NN are identity rows, A00=ANN=1A_{00}=A_{NN}=1 and nothing else (the solid frames in the left panel of Figure 15). So the Newton correction satisfies ΔU0=−R0\Delta U_0=-R_0: after the first step U0=uinU_0=u_{\rm in} holds exactly, because the constraint row is linear; the initial guess of this page is already exact at both ends (it is the vector of exact nodal values), so every correction is zero there. The boundary nodes remain neighbours of the interior rows: at second order U0U_0 occurs in rows 1,21,2 and UNU_N in rows N−2,N−1N-2,N-1 (the dashed frames of Figure 15; at first order U0U_0 occurs in row 11 only and UNU_N in row N−1N-1 only), the “boundary columns” of AA. Section 6 shows that AA is therefore block triangular, with det⁡A=det⁡AII\det A=\det A_{\rm II}, where AIIA_{\rm II} is the interior block that remains when the two constraint rows and the two boundary columns are removed.

对 RDR_D 的作用:边界数据只进入这两个约束行。uin=u∗(0)=1−a sin⁡2πφu_{\rm in}=u^*(0)=1-a\,\sin2\pi\varphi,又因为 u∗u^* 的周期为 1,uout=uinu_{\rm out}=u_{\rm in},所以

The effect on RDR_D: the boundary data enter these two rows and nowhere else. uin=u∗(0)=1−a sin⁡2πφu_{\rm in}=u^*(0)=1-a\,\sin2\pi\varphi, and since u∗u^* has period 1, uout=uinu_{\rm out}=u_{\rm in}, so

∂R0∂D=∂RN∂D=−∂uin∂D=(sin⁡2πφ, 2πa cos⁡2πφ, 0)=(0.425779, 1.137039, 0).\frac{\partial R_0}{\partial D}=\frac{\partial R_N}{\partial D}=-\frac{\partial u_{\rm in}}{\partial D}=\bigl(\sin2\pi\varphi,\ 2\pi a\,\cos2\pi\varphi,\ 0\bigr)=\bigl(0.425779,\ 1.137039,\ 0\bigr).

没有 ν\nu 分量:u∗u^* 不依赖 ν\nu,边界数据也不依赖。第 1,…,N−11,\dots,N-1 行里不出现 uin,uoutu_{\rm in},u_{\rm out} 本身,只出现状态 U0,UNU_0,U_N;设计变量通过 QfQ_f(含 a,φ,νa,\varphi,\nu)和通量里的 ν\nu 进入这些行。(格心页相反:那里 uinu_{\rm in} 在边界面通量里,RDR_D 的第一行带着它。)两个约束行的乘子,也就是伴随方程在这两行上的分量 ψ0,ψN\psi_0,\psi_N,会在第 9、11 节登场。

There is no ν\nu component: u∗u^* does not depend on ν\nu, so neither do the boundary data. Rows 1,…,N−11,\dots,N-1 do not contain uinu_{\rm in} or uoutu_{\rm out} themselves, only the states U0,UNU_0,U_N; the design enters them through QfQ_f (through a,φ,νa,\varphi,\nu) and through ν\nu in the flux. (On the cell-centred page it is the other way round: there uinu_{\rm in} sits inside the end-face flux, and the first row of RDR_D carries it.) The multipliers of the two constraint rows, the components ψ0,ψN\psi_0,\psi_N of the adjoint on these rows, appear in Sections 9 and 11.

图 15 · 约束行在 A 与 R_D 中的位置(默认设计的收敛解,N=8,无限制器线性)。左:A,蓝色为正、橙色为负;第 0 行与第 N 行是单位行(实线框),边界节点的列(虚线框)只出现在紧邻的内部行里。右:R_D 的三列 a,φ,ν;只有第 0 行和第 N 行(实线框)含边界数据的导数,两行相同。1.00−1.101.37−0.240.110.39−1.941.69−0.190.100.40−1.971.62−0.230.110.39−1.911.58−0.330.130.37−1.811.58−0.430.140.36−1.711.63−0.470.150.35−1.691.55−0.151.00012345678012345678A = RU​(N = 8,无限制器线性)0.431.14−0.83−0.130.11−0.48−0.96−0.020.30−1.06−0.080.78−0.35−0.120.650.41−0.100.260.730.05−0.120.790.340.431.14aφν012345678RD​实线框:两个约束行(单位行)虚线框:边界节点的列
图 15 · 约束行在 AA 与 RDR_D 中的位置(默认设计的收敛解,N=8N=8,无限制器线性)。左:AA,蓝色为正、橙色为负;第 00 行与第 NN 行是单位行(实线框),边界节点的列(虚线框)只出现在紧邻的内部行里。右:RDR_D 的三列 a,φ,νa,\varphi,\nu;只有第 00 行和第 NN 行(实线框)含边界数据的导数,两行相同。
Figure 15 · The constraint rows in A and R_D (converged solution of the default design, N=8, unlimited linear). Left: A, blue positive and orange negative; rows 0 and N are identity rows (solid frames), and the columns of the boundary nodes (dashed frames) appear only in the interior rows next to them. Right: the three columns a,φ,ν of R_D; only rows 0 and N (solid frames) contain the derivative of the boundary data, and the two rows are equal.1.00−1.101.37−0.240.110.39−1.941.69−0.190.100.40−1.971.62−0.230.110.39−1.911.58−0.330.130.37−1.811.58−0.430.140.36−1.711.63−0.470.150.35−1.691.55−0.151.00012345678012345678A = RU​ (N = 8, unlimited linear)0.431.14−0.83−0.130.11−0.48−0.96−0.020.30−1.06−0.080.78−0.35−0.120.650.41−0.100.260.730.05−0.120.790.340.431.14aφν012345678RD​solid frames: the two constraint rows (identity rows)dashed frames: the columns of the boundary nodes
Figure 15 · The constraint rows in AA and RDR_D (converged solution of the default design, N=8N=8, unlimited linear). Left: AA, blue positive and orange negative; rows 00 and NN are identity rows (solid frames), and the columns of the boundary nodes (dashed frames) appear only in the interior rows next to them. Right: the three columns a,φ,νa,\varphi,\nu of RDR_D; only rows 00 and NN (solid frames) contain the derivative of the boundary data, and the two rows are equal.

边界面读什么

What the boundary faces read

面 00 在节点 00 与节点 11 之间,面 N−1N-1 在节点 N−1N-1 与节点 NN 之间。它们与内部面完全相同:两侧各有一个节点,黏性差商的距离是 df=hd_f=h,没有半个间距。唯一特殊的是边界节点的斜率。内部节点有两个邻居,边界节点只有一个,所以用单侧差分:二阶重构取 σ0=U1−U0\sigma_0=U_1-U_0、σN=UN−UN−1\sigma_N=U_N-U_{N-1};一阶格式所有节点的斜率都是零;光滑限制器需要两个邻居,所以边界斜率不加限制。格式不造虚拟节点。无限制器线性重构时:

Face 00 lies between node 00 and node 11, face N−1N-1 between node N−1N-1 and node NN. They are exactly like the interior faces: a node on each side and the distance df=hd_f=h in the viscous quotient, no half-interval distance. The only special thing is the slope of a boundary node. An interior node has two neighbours, a boundary node has one, so it uses a one-sided difference: at second order σ0=U1−U0\sigma_0=U_1-U_0 and σN=UN−UN−1\sigma_N=U_N-U_{N-1}; at first order every slope is zero; the smooth limiter needs both neighbours, so the boundary slopes are not limited. The scheme invents no ghost node. For unlimited linear reconstruction:

qL(0)=U0+12σ0=12(U0+U1),qR(0)=U1−12σ1=U1−14(U2−U0),qL(N−1)=UN−1+12σN−1=UN−1+14(UN−UN−2),qR(N−1)=UN−12σN=12(UN−1+UN).\begin{aligned}q_L(0)&=U_0+\tfrac12\sigma_0=\tfrac12(U_0+U_1),& q_R(0)&=U_1-\tfrac12\sigma_1=U_1-\tfrac14(U_2-U_0),\\ q_L(N-1)&=U_{N-1}+\tfrac12\sigma_{N-1}=U_{N-1}+\tfrac14(U_N-U_{N-2}),& q_R(N-1)&=U_N-\tfrac12\sigma_N=\tfrac12(U_{N-1}+U_N).\end{aligned}

于是面 00 读三个数 U0,U1,U2U_0,U_1,U_2(U0U_0 是约束给定的值),面 N−1N-1 读 UN−2,UN−1,UNU_{N-2},U_{N-1},U_N;其余内部面读四个。注意 qL(0)q_L(0) 就是两个节点的平均,也就是线性插值在面中点的值。

So face 00 reads three numbers U0,U1,U2U_0,U_1,U_2 (U0U_0 is the value the constraint fixes) and face N−1N-1 reads UN−2,UN−1,UNU_{N-2},U_{N-1},U_N; the other faces read four. Note that qL(0)q_L(0) is just the mean of the two nodes, the value of the linear interpolant at the face midpoint.

图 16 · 两个边界区域读的数据(默认设计的收敛解,N=8,无限制器线性重构)。每个节点有自己的对偶控制体(两个边界节点的控制体只有一半宽),控制体里的线段是线性重构;虚线竖线是面,面上的两个圆圈是左右两个迹 q_L(橙)与 q_R(绿),它们之间的间隔是 Rusanov 耗散的来源。紫色方块是给定的边界值。每一端旁边:边界面通量的分项和它的导数,数字来自本页的模型。左端:节点 0 在 x = 0,行 0 是约束 R0​ = U0​ − uin​U0​节点 0σ 单侧U1​节点 1U2​节点 2U3​节点 3uin​面 0d = h,与内部面相同σ0​ = U1​ − U0​ = 0.15529(单侧)qL​ = U0​ + σ0​/2 = 0.99249qR​ = U1​ − σ1​/2 = 1.00615Hc​ = 0.48569,Hv​ = −0.01242,H0​ = 0.47326∂H0​/∂U0​ = cL​/2 + cR​/4 + ν/h = 0.7039∂H0​/∂U1​ = cL​/2 + cR​ − ν/h = 0.1712∂H0​/∂U2​ = −cR​/4 = 0.1242右端:节点 N = 8 在 x = 1,行 N 是约束 RN​ = UN​ − uout​U5​节点 5U6​节点 6U7​节点 7U8​节点 8σ 单侧uout​面 7d = h,与内部面相同σN​ = UN​ − UN−1​ = 0.08205(单侧)qL​ = UN−1​ + σN−1​/2 = 0.85604qR​ = UN​ − σN​/2 = 0.87382Hc​ = 0.35631,Hv​ = −0.00656,HN−1​ = 0.34975∂H/∂UN−2​ = −cL​/4 = −0.3570∂H/∂UN−1​ = cL​ + cR​/2 + ν/h = 1.2265∂H/∂UN​ = cL​/4 + cR​/2 − ν/h = −0.0045
图 16 · 两个边界区域读的数据(默认设计的收敛解,N=8N=8,无限制器线性重构)。每个节点有自己的对偶控制体(两个边界节点的控制体只有一半宽),控制体里的线段是线性重构;虚线竖线是面,面上的两个圆圈是左右两个迹 qLq_L(橙)与 qRq_R(绿),它们之间的间隔是 Rusanov 耗散的来源。紫色方块是给定的边界值。每一端旁边:边界面通量的分项和它的导数,数字来自本页的模型。
Figure 16 · What the two boundary regions read (converged solution of the default design, N=8, unlimited linear reconstruction). Each node has its own dual volume (the two boundary volumes are half as wide) and the segment in it is the linear reconstruction; the vertical dashed line is the face, and the two circles on it are the left and right traces q_L (orange) and q_R (green), whose gap is the source of the Rusanov dissipation. The violet squares are the prescribed boundary values. Beside each end: the parts of the boundary-face flux and its derivatives, numbers from the page's model.left end: node 0 sits at x = 0, row 0 is the constraint R0​ = U0​ − uin​U0​node 0σ one-sidedU1​node 1U2​node 2U3​node 3uin​face 0d = h, as at an interior faceσ0​ = U1​ − U0​ = 0.15529 (one-sided)qL​ = U0​ + σ0​/2 = 0.99249qR​ = U1​ − σ1​/2 = 1.00615Hc​ = 0.48569, Hv​ = −0.01242, H0​ = 0.47326∂H0​/∂U0​ = cL​/2 + cR​/4 + ν/h = 0.7039∂H0​/∂U1​ = cL​/2 + cR​ − ν/h = 0.1712∂H0​/∂U2​ = −cR​/4 = 0.1242right end: node N = 8 sits at x = 1, row N is the constraint RN​ = UN​ − uout​U5​node 5U6​node 6U7​node 7U8​node 8σ one-sideduout​face 7d = h, as at an interior faceσN​ = UN​ − UN−1​ = 0.08205 (one-sided)qL​ = UN−1​ + σN−1​/2 = 0.85604qR​ = UN​ − σN​/2 = 0.87382Hc​ = 0.35631, Hv​ = −0.00656, HN−1​ = 0.34975∂H/∂UN−2​ = −cL​/4 = −0.3570∂H/∂UN−1​ = cL​ + cR​/2 + ν/h = 1.2265∂H/∂UN​ = cL​/4 + cR​/2 − ν/h = −0.0045
Figure 16 · What the two boundary regions read (converged solution of the default design, N=8N=8, unlimited linear reconstruction). Each node has its own dual volume (the two boundary volumes are half as wide) and the segment in it is the linear reconstruction; the vertical dashed line is the face, and the two circles on it are the left and right traces qLq_L (orange) and qRq_R (green), whose gap is the source of the Rusanov dissipation. The violet squares are the prescribed boundary values. Beside each end: the parts of the boundary-face flux and its derivatives, numbers from the page's model.

边界面通量与它的导数

The boundary-face flux and its derivatives

面 00 的通量就是第 3 节的 HfH_f,只是输入里有一个是边界值:

The flux of face 00 is the HfH_f of Section 3, with one boundary value among its inputs:

H0=14(qL2+qR2)−(qR−qL)−νh (U1−U0),qL=12(U0+U1),qR=U1−14(U2−U0).H_0=\tfrac14\bigl(q_L^2+q_R^2\bigr)-\bigl(q_R-q_L\bigr)-\frac\nu h\,(U_1-U_0),\qquad q_L=\tfrac12(U_0+U_1),\quad q_R=U_1-\tfrac14(U_2-U_0).

它的导数只需要第 3 节的局部导数 cL=qL/2+1c_L=q_L/2+1、cR=qR/2−1c_R=q_R/2-1、κ=ν/h\kappa=\nu/h 与上面的迹对 U0,U1,U2U_0,U_1,U_2 的导数:

Its derivatives need only the local derivatives of Section 3, cL=qL/2+1c_L=q_L/2+1, cR=qR/2−1c_R=q_R/2-1, κ=ν/h\kappa=\nu/h, and the derivatives of the traces above with respect to U0,U1,U2U_0,U_1,U_2:

∂H0∂U0=cL2+cR4+κ,∂H0∂U1=cL2+cR−κ,∂H0∂U2=−cR4,∂H0∂ν=−U1−U0h.\frac{\partial H_0}{\partial U_0}=\frac{c_L}2+\frac{c_R}4+\kappa,\qquad\frac{\partial H_0}{\partial U_1}=\frac{c_L}2+c_R-\kappa,\qquad\frac{\partial H_0}{\partial U_2}=-\frac{c_R}4,\qquad\frac{\partial H_0}{\partial\nu}=-\frac{U_1-U_0}h.

在默认设计(N=8N=8,无限制器线性):uin=U0=0.914844u_{\rm in}=U_0=0.914844,U1=1.070138U_1=1.070138,U2=1.170809U_2=1.170809,σ0=0.155294\sigma_0=0.155294,qL=0.992491q_L=0.992491,qR=1.006147q_R=1.006147,Hc=0.485687H^c=0.485687,Hv=−0.012424H^v=−0.012424,H0=0.473263H_0=0.473263,∂H0/∂U0=0.70389\partial H_0/\partial U_0=0.70389,∂H0/∂U1=0.17120\partial H_0/\partial U_1=0.17120,∂H0/∂U2=0.12423\partial H_0/\partial U_2=0.12423,∂H0/∂ν=−1.24235\partial H_0/\partial\nu=−1.24235。第 8 节的前向代码以 𝐔˙=e0,e1,e2\dot{\mathbf U}=e_0,e_1,e_2(以及右端的 eN−2,eN−1,eNe_{N-2},e_{N-1},e_N)和 D˙=eν\dot D=e_\nu 为种子,得到的 H˙\dot H 与这些公式一致(无限制器线性;另两种重构与用各自迹权重(第 3 节)写出的同一链式法则一致;三种重构的最大差不超过 10−1510^{-15})。

At the defaults (N=8N=8, unlimited linear): uin=U0=0.914844u_{\rm in}=U_0=0.914844, U1=1.070138U_1=1.070138, U2=1.170809U_2=1.170809, σ0=0.155294\sigma_0=0.155294, qL=0.992491q_L=0.992491, qR=1.006147q_R=1.006147, Hc=0.485687H^c=0.485687, Hv=−0.012424H^v=−0.012424, H0=0.473263H_0=0.473263, ∂H0/∂U0=0.70389\partial H_0/\partial U_0=0.70389, ∂H0/∂U1=0.17120\partial H_0/\partial U_1=0.17120, ∂H0/∂U2=0.12423\partial H_0/\partial U_2=0.12423, ∂H0/∂ν=−1.24235\partial H_0/\partial\nu=−1.24235. The forward code of Section 8, seeded with 𝐔˙=e0,e1,e2\dot{\mathbf U}=e_0,e_1,e_2 (and eN−2,eN−1,eNe_{N-2},e_{N-1},e_N at the right end) and D˙=eν\dot D=e_\nu, returns H˙\dot H equal to these formulas for unlimited linear (for the other two reconstructions, equal to the same chain rule with their trace weights of Section 3; the largest difference over all three is at most 10−1510^{-15}).

这些导数去了 AA 的哪里?R1=H1−H0−S1R_1=H_1-H_0-S_1 含 −H0-H_0,所以第 11 行的 A1,0,A1,1,A1,2A_{1,0},A_{1,1},A_{1,2} 各含一项 −∂H0/∂Uk-\partial H_0/\partial U_k:黏性部分给 A11A_{11} 加上 κ=ν/h\kappa=\nu/h,加强了对角元。设计变量通过 ∂H0/∂ν\partial H_0/\partial\nu 进入 RDR_D 的第 11 行(还有 Q0,Q1Q_0,Q_1 的导数)。

Where do these derivatives go in AA? R1=H1−H0−S1R_1=H_1-H_0-S_1 contains −H0-H_0, so A1,0,A1,1,A1,2A_{1,0},A_{1,1},A_{1,2} each contain a term −∂H0/∂Uk-\partial H_0/\partial U_k: the viscous part adds κ=ν/h\kappa=\nu/h to A11A_{11} and strengthens the diagonal. The design enters row 11 of RDR_D through ∂H0/∂ν\partial H_0/\partial\nu (and through the derivatives of Q0Q_0 and Q1Q_1).

试一试:调节 U1,U2U_1,U_2 与 uinu_{\rm in},看边界面通量的两部分、它的三个偏导数和单侧斜率;按钮把 U1,U2U_1,U_2 设成精确节点值或求解后的值,也可以切换重构。

Try it: adjust U1,U2U_1,U_2 and uinu_{\rm in} and watch the two parts of the boundary-face flux, its three partial derivatives and the one-sided slope; the buttons set U1,U2U_1,U_2 to the exact nodal values or to the solved values, and the reconstruction can be switched.

单侧斜率的代价

What the one-sided slope costs

设 uu 光滑。把 uu 在 x=0x=0 处展开:

Let uu be smooth. Expanding uu about x=0x=0 gives

σ0h=u(h)−u(0)h=u′(0)+h2u′′(0)+h26u′′′(0)+O(h3).\frac{\sigma_0}h=\frac{u(h)-u(0)}h=u'(0)+\frac h2u''(0)+\frac{h^2}6u'''(0)+O(h^3).

边界节点的斜率只有一阶精度,主误差为 h2u′′(0)\tfrac h2u''(0)。但斜率进入面通量时要乘上 h/2h/2(qL(0)=U0+σ0/2q_L(0)=U_0+\sigma_0/2),所以面上的迹仍是二阶的;黏性差商则与内部面一样,是中心差商:

The slope of the boundary node is only first-order accurate, with leading error h2u′′(0)\tfrac h2u''(0). But it enters the face flux multiplied by h/2h/2 (qL(0)=U0+σ0/2q_L(0)=U_0+\sigma_0/2), so the trace at the face is still second-order accurate, and the viscous quotient is the same centred quotient as at an interior face:

qL(0)−u(h2)=h28u′′(0)+O(h3),U1−U0h−u′(h2)=h224u′′′(h2)+O(h4).q_L(0)-u\bigl(\tfrac h2\bigr)=\frac{h^2}8u''(0)+O(h^3),\qquad\frac{U_1-U_0}h-u'\bigl(\tfrac h2\bigr)=\frac{h^2}{24}u'''\bigl(\tfrac h2\bigr)+O(h^4).

单侧斜率留下的痕迹在 Rusanov 项里。内部面的两个迹互为镜像(把 uu 在面中点展开:qL=u−h28u′′+h38u′′′q_L=u-\tfrac{h^2}8u''+\tfrac{h^3}8u''',qR=u−h28u′′−h38u′′′q_R=u-\tfrac{h^2}8u''-\tfrac{h^3}8u'''),所以 qR−qL=−h34u′′′+O(h5)q_R-q_L=-\tfrac{h^3}4u'''+O(h^5) 是三阶小量。面 00 的 qRq_R 用内部斜率 σ1\sigma_1,qLq_L 用单侧斜率 σ0\sigma_0,对称性不再成立:

The one-sided slope leaves its mark in the Rusanov term. At an interior face the two traces are mirror images (expand uu about the face midpoint: qL=u−h28u′′+h38u′′′q_L=u-\tfrac{h^2}8u''+\tfrac{h^3}8u''', qR=u−h28u′′−h38u′′′q_R=u-\tfrac{h^2}8u''-\tfrac{h^3}8u'''), so qR−qL=−h34u′′′+O(h5)q_R-q_L=-\tfrac{h^3}4u'''+O(h^5) is of third order. At face 00 the trace qRq_R uses the interior slope σ1\sigma_1 and qLq_L the one-sided slope σ0\sigma_0, and the symmetry is gone:

qR(0)−qL(0)=−h24u′′(0)+O(h3).q_R(0)-q_L(0)=-\frac{h^2}4u''(0)+O(h^3).

它比内部面大一阶,但仍然是二阶。下表把这五个量的展开主项与精确节点值上的实测对照(N=4096N=4096)。

That is one order larger than at an interior face, but still second order. The table compares the leading terms of the expansions of these five quantities with what is measured at the exact nodal values (N=4096N=4096).

量Quantity除以divided by展开的主项leading termN=4096N=4096 的实测measured at N=4096N=4096
σ0/h−u∗′(0)\sigma_0/h-u^{*\prime}(0)hhu∗′′(0)/2=1.6809u^{*\prime\prime}(0)/2=1.68091.6791
qL(0)−u∗(h/2)q_L(0)-u^*(h/2)h2h^2u∗′′(0)/8=0.4202u^{*\prime\prime}(0)/8=0.42020.4195
(U1−U0)/h−u∗′(h/2)(U_1-U_0)/h-u^{*\prime}(h/2)h2h^2u∗′′′(0)/24=−1.8704u^{*\prime\prime\prime}(0)/24=-1.8704−1.8710
qR(0)−qL(0)q_R(0)-q_L(0)h2h^2−u∗′′(0)/4=−0.8405-u^{*\prime\prime}(0)/4=-0.8405−0.8377
x=12x=\tfrac12 处的 qR−qLq_R-q_LqR−qLq_R-q_L at x=12x=\tfrac12h3h^3−u∗′′′(12)/4=−11.222-u^{*\prime\prime\prime}(\tfrac12)/4=-11.222−11.226
图 17 · 单侧斜率的代价(精确节点值,默认设计)。紫:边界节点的斜率误差,一阶;绿(空心):面上的迹 q_L(0) 的误差,二阶;蓝方块:面 0 的黏性差商的误差,二阶(与内部面一样);橙虚线:面 0 的 Rusanov 跳跃 q_R-q_L,二阶;灰虚线:内部面 x=1/2 的跳跃,三阶。点线是 h,h^2,h^3 的参考斜率。格心页的半格差商只有一阶:那里的边界面是一阶的,这里不是。10-12​10-10​10-8​10-6​10-4​10-2​1101001000N误差hh²h³单侧斜率 σ0​/h − u*′(0)面上的迹 qL​(0) − u*(h/2)黏性差商 (U1​ − U0​)/h − u*′(h/2)面 0 的跳跃 qR​ − qL​内部面 x = 1/2 的跳跃
图 17 · 单侧斜率的代价(精确节点值,默认设计)。紫:边界节点的斜率误差,一阶;绿(空心):面上的迹 qL(0)q_L(0) 的误差,二阶;蓝方块:面 00 的黏性差商的误差,二阶(与内部面一样);橙虚线:面 00 的 Rusanov 跳跃 qR−qLq_R-q_L,二阶;灰虚线:内部面 x=12x=\tfrac12 的跳跃,三阶。点线是 h,h2,h3h,h^2,h^3 的参考斜率。格心页的半格差商只有一阶:那里的边界面是一阶的,这里不是。
Figure 17 · What the one-sided slope costs (exact nodal values, default design). Violet: the slope error of the boundary node, first order; green (open): the error of the trace q_L(0), second order; blue squares: the error of the viscous quotient of face 0, second order (as at an interior face); dashed orange: the Rusanov jump q_R-q_L of face 0, second order; dashed grey: the jump at the interior face x=1/2, third order. Dotted lines are reference slopes h,h^2,h^3. The half-cell quotient of the cell-centred page is only first order: its boundary face is first order, this one is not.10-12​10-10​10-8​10-6​10-4​10-2​1101001000Nerrorhh²h³one-sided slope σ0​/h − u*′(0)trace qL​(0) − u*(h/2)viscous quotient (U1​ − U0​)/h − u*′(h/2)jump qR​ − qL​ at face 0jump at the interior face x = 1/2
Figure 17 · What the one-sided slope costs (exact nodal values, default design). Violet: the slope error of the boundary node, first order; green (open): the error of the trace qL(0)q_L(0), second order; blue squares: the error of the viscous quotient of face 00, second order (as at an interior face); dashed orange: the Rusanov jump qR−qLq_R-q_L of face 00, second order; dashed grey: the jump at the interior face x=12x=\tfrac12, third order. Dotted lines are reference slopes h,h2,h3h,h^2,h^3. The half-cell quotient of the cell-centred page is only first order: its boundary face is first order, this one is not.

面误差

The face errors

对每个面定义面误差 ζf=Hf(𝐮∗)−Qf\zeta_f=H_f(\mathbf u^*)-Q_f:精确节点值 𝐮∗=(u∗(x0),…,u∗(xN))T\mathbf u^*=(u^*(x_0),\dots,u^*(x_N))^T 上的数值通量减去精确通量。把上面的展开代进通量 HfH_f(对流部分 14(qL2+qR2)−(qR−qL)\tfrac14(q_L^2+q_R^2)-(q_R-q_L) 加黏性部分),在面中点处展开,无限制器线性重构得到:

For every face define the face error ζf=Hf(𝐮∗)−Qf\zeta_f=H_f(\mathbf u^*)-Q_f: the numerical flux at the vector of exact nodal values 𝐮∗=(u∗(x0),…,u∗(xN))T\mathbf u^*=(u^*(x_0),\dots,u^*(x_N))^T minus the exact flux. Putting the expansions above into the flux HfH_f (the convective part 14(qL2+qR2)−(qR−qL)\tfrac14(q_L^2+q_R^2)-(q_R-q_L) plus the viscous part) and expanding about the face midpoint, unlimited linear reconstruction gives:

ζf=−h2(u u′′8+ν u′′′24)+O(h3)(1≤f≤N−2),ζ0=   h2(u′′(0)4−ν u′′′(0)24)+O(h3),ζN−1=−h2(u′′(1)4+ν u′′′(1)24)+O(h3).\begin{aligned}\zeta_f&=-h^2\Bigl(\frac{u\,u''}8+\frac{\nu\,u'''}{24}\Bigr)+O(h^3)&&(1\le f\le N-2),\\ \zeta_0&=\ \ \ h^2\Bigl(\frac{u''(0)}4-\frac{\nu\,u'''(0)}{24}\Bigr)+O(h^3),\\ \zeta_{N-1}&=-h^2\Bigl(\frac{u''(1)}4+\frac{\nu\,u'''(1)}{24}\Bigr)+O(h^3).\end{aligned}

推导:内部面 14(qL2+qR2)=12u2−h28u u′′+O(h4)\tfrac14(q_L^2+q_R^2)=\tfrac12u^2-\tfrac{h^2}8u\,u''+O(h^4),黏性差商 −νu′−νh224u′′′-\nu u'-\tfrac{\nu h^2}{24}u''',Rusanov 项只有 O(h3)O(h^3),减去 Qf=12u2−νu′Q_f=\tfrac12u^2-\nu u' 即得第一行。面 00 里 qL−u=+h28u′′q_L-u=+\tfrac{h^2}8u''、qR−u=−h28u′′q_R-u=-\tfrac{h^2}8u'',所以 14(qL2+qR2)\tfrac14(q_L^2+q_R^2) 的 h2h^2 项抵消,剩下的是 Rusanov 项 −(qR−qL)=+h24u′′-(q_R-q_L)=+\tfrac{h^2}4u'' 和黏性项。边界面的面误差与内部面同阶,O(h2)O(h^2),只是系数不同:在默认设计,内部面误差在两端的极限值是 −(uu′′/8+νu′′′/24)=−0.3657-(uu''/8+\nu u'''/24)=-0.3657,面 00 的系数是 0.8592,面 N−1N-1 的系数是 −0.8218(N=4096N=4096 的实测:0.8571 与 −0.8251)。一阶格式的所有面(包括两个边界面)都是 ζf=−h u∗′(xf+1/2)+O(h2)\zeta_f=-h\,u^{*\prime}(x_{f+1/2})+O(h^2):迹就是节点值,边界面没有任何特殊之处。

Derivation: at an interior face 14(qL2+qR2)=12u2−h28u u′′+O(h4)\tfrac14(q_L^2+q_R^2)=\tfrac12u^2-\tfrac{h^2}8u\,u''+O(h^4), the viscous quotient is −νu′−νh224u′′′-\nu u'-\tfrac{\nu h^2}{24}u''', the Rusanov term is only O(h3)O(h^3), and subtracting Qf=12u2−νu′Q_f=\tfrac12u^2-\nu u' gives the first line. At face 00 one has qL−u=+h28u′′q_L-u=+\tfrac{h^2}8u'' and qR−u=−h28u′′q_R-u=-\tfrac{h^2}8u'', so the h2h^2 terms of 14(qL2+qR2)\tfrac14(q_L^2+q_R^2) cancel and what remains is the Rusanov term −(qR−qL)=+h24u′′-(q_R-q_L)=+\tfrac{h^2}4u'' and the viscous term. The face errors of the boundary faces are of the same order as those of the interior faces, O(h2)O(h^2), only the coefficients differ: at the default design the limit of the interior face error at the two ends is −(uu′′/8+νu′′′/24)=−0.3657-(uu''/8+\nu u'''/24)=-0.3657, the coefficient of face 00 is 0.8592 and that of face N−1N-1 is −0.8218 (measured at N=4096N=4096: 0.8571 and −0.8251). At first order every face, the two boundary faces included, has ζf=−h u∗′(xf+1/2)+O(h2)\zeta_f=-h\,u^{*\prime}(x_{f+1/2})+O(h^2): the traces are the nodal values and nothing is special at the boundary.

图 18 · 面误差 ζ_f=H_f(u*)-Q_f 沿面的分布(N=64,默认设计)。左:无限制器线性,ζ_f/h^2;虚线是内部面的极限 -(uu''/8+ν u'''/24),两个紫色方块是边界面 f=0,N-1:它们偏离内部曲线,但与内部面同阶。右:一阶,ζ_f/h,虚线是极限 -u*′(x),两个边界面落在同一条曲线上。−1−0.500.5100.20.40.60.81面的位置 xf+1/2​ζf​ / h²无限制器线性内部极限 −(u u″/8 + ν u‴/24)内部面 f = 1 … N−2边界面 f = 0, N−1−1−0.500.5100.20.40.60.81面的位置 xf+1/2​ζf​ / h一阶极限 −u*′(x)内部面边界面
图 18 · 面误差 ζf=Hf(𝐮∗)−Qf\zeta_f=H_f(\mathbf u^*)-Q_f 沿面的分布(N=64N=64,默认设计)。左:无限制器线性,ζf/h2\zeta_f/h^2;虚线是内部面的极限 −(uu′′/8+νu′′′/24)-(uu''/8+\nu u'''/24),两个紫色方块是边界面 f=0,N−1f=0,N-1:它们偏离内部曲线,但与内部面同阶。右:一阶,ζf/h\zeta_f/h,虚线是极限 −u∗′(x)-u^{*\prime}(x),两个边界面落在同一条曲线上。
Figure 18 · The face errors ζ_f=H_f(u*)-Q_f along the faces (N=64, default design). Left: unlimited linear, ζ_f/h^2; the dashed curve is the limit -(uu''/8+ν u'''/24) of the interior faces, and the two violet squares are the boundary faces f=0,N-1: they leave the interior curve but are of the same order. Right: first order, ζ_f/h, the dashed curve is the limit -u*′(x) and the two boundary faces lie on the same curve.−1−0.500.5100.20.40.60.81face position xf+1/2​ζf​ / h²unlimited linearinterior limit −(u u″/8 + ν u‴/24)interior faces f = 1 … N−2boundary faces f = 0, N−1−1−0.500.5100.20.40.60.81face position xf+1/2​ζf​ / hfirst orderlimit −u*′(x)interior facesboundary faces
Figure 18 · The face errors ζf=Hf(𝐮∗)−Qf\zeta_f=H_f(\mathbf u^*)-Q_f along the faces (N=64N=64, default design). Left: unlimited linear, ζf/h2\zeta_f/h^2; the dashed curve is the limit −(uu′′/8+νu′′′/24)-(uu''/8+\nu u'''/24) of the interior faces, and the two violet squares are the boundary faces f=0,N−1f=0,N-1: they leave the interior curve but are of the same order. Right: first order, ζf/h\zeta_f/h, the dashed curve is the limit −u∗′(x)-u^{*\prime}(x) and the two boundary faces lie on the same curve.

截断误差:边界行与内部行

The truncation error: boundary rows against interior rows

把精确节点值代入残差,看它离零有多远,这就是截断误差。两个约束行恒为零:R0(𝐮∗)=RN(𝐮∗)=0R_0(\mathbf u^*)=R_N(\mathbf u^*)=0,因为给定的就是精确值,约束行在边界上没有任何误差。其余各行的源项是精确的(第 5 节),所以残差就是相邻两个面误差的差:

Put the exact nodal values into the residual and see how far it is from zero: that is the truncation error. The two constraint rows vanish identically, R0(𝐮∗)=RN(𝐮∗)=0R_0(\mathbf u^*)=R_N(\mathbf u^*)=0, because the prescribed values are the exact ones: the constraint rows carry no error at all. The source of the other rows is exact (Section 5), so the residual is the difference of two neighbouring face errors:

Rj(𝐮∗)=ζj−ζj−1(1≤j≤N−1).R_j(\mathbf u^*)=\zeta_j-\zeta_{j-1}\quad(1\le j\le N-1).

无限制器线性重构时,面 1,…,N−21,\dots,N-2 的 ζf\zeta_f 是 ff 的光滑函数,大小 O(h2)O(h^2);相邻两项之差再小一阶,所以第 2,…,N−22,\dots,N-2 行是 O(h3)O(h^3)。第 11 行和第 N−1N-1 行把一个边界面和一个内部面相比:两者都是 O(h2)O(h^2),系数不同,所以这两行是 O(h2)O(h^2),系数分别是 R1≈h2(ζint(0)−z0)=−1.2249 h2R_1\approx h^2\bigl(\zeta_{\rm int}(0)-z_0\bigr)=-1.2249\,h^2 与 RN−1≈h2(zN−1−ζint(1))=−0.4560 h2R_{N-1}\approx h^2\bigl(z_{N-1}-\zeta_{\rm int}(1)\bigr)=-0.4560\,h^2(N=4096N=4096 的实测:−1.2238 与 −0.4549)。因此紧邻边界的两行比内部行低一阶,但仍然 O(h2)O(h^2):用残差密度 Rj/hR_j/h(通常意义的局部截断误差)看,每一行都趋于零,N=4096N=4096 时 ∣R1∣/h=3×10−4|R_1|/h=3\times10^{-4}。格心页的端行不是这样:那里 R0/hR_0/h 与 R1/hR_1/h 趋于常数 −0.51-0.51 和 0.830.83,端行在逐点意义上是不相容的。

With unlimited linear reconstruction the ζf\zeta_f of faces 1,…,N−21,\dots,N-2 are a smooth function of ff of size O(h2)O(h^2); the difference of two neighbours is one power of hh smaller, so rows 2,…,N−22,\dots,N-2 are O(h3)O(h^3). Rows 11 and N−1N-1 compare a boundary face with an interior face: both are O(h2)O(h^2) with different coefficients, so these two rows are O(h2)O(h^2), with the coefficients R1≈h2(ζint(0)−z0)=−1.2249 h2R_1\approx h^2\bigl(\zeta_{\rm int}(0)-z_0\bigr)=-1.2249\,h^2 and RN−1≈h2(zN−1−ζint(1))=−0.4560 h2R_{N-1}\approx h^2\bigl(z_{N-1}-\zeta_{\rm int}(1)\bigr)=-0.4560\,h^2 (measured at N=4096N=4096: −1.2238 and −0.4549). So the two rows next to the boundary are one order less accurate than the interior rows, but still O(h2)O(h^2): in the residual density Rj/hR_j/h, the usual local truncation error, every row tends to zero, ∣R1∣/h=3×10−4|R_1|/h=3\times10^{-4} at N=4096N=4096. The end rows of the cell-centred page are not like this: there R0/hR_0/h and R1/hR_1/h tend to the constants −0.51-0.51 and 0.830.83, and the end rows are inconsistent in the pointwise sense.

一阶格式没有这种区别:所有面都有 ζf=−h u∗′+O(h2)\zeta_f=-h\,u^{*\prime}+O(h^2),所以每个内部行(包括第 11 行和第 N−1N-1 行)都是 Rj=−h2u∗′′(xj)+O(h3)R_j=-h^2u^{*\prime\prime}(x_j)+O(h^3)。N=4096N=4096 时最大的内部行除以 h2h^2 是 7.8957(max⁡∣u∗′′∣=4π2a=7.8957\max|u^{*\prime\prime}|=4\pi^2a=7.8957),第 11 行是 −3.3517(−u∗′′(0)=−3.3618-u^{*\prime\prime}(0)=-3.3618)。光滑限制器在细网格上有一点特别:ϵ=0.01\epsilon=0.01 固定,内部斜率的两个差分 lj,rj≈h ux∗≪ϵl_j,r_j\approx h\,u^*_x\ll\epsilon,限制器把内部斜率压到几乎为零,内部面于是像一阶面;而边界斜率是单侧的、不加限制,不会被压掉,所以边界面仍像带斜率的二阶面。两种面的误差差一个 O(h)O(h):R1/h→−u∗′(0)(12+uin4)=−0.8286R_1/h\to-u^{*\prime}(0)\bigl(\tfrac12+\tfrac{u_{\rm in}}4\bigr)=-0.8286,RN−1/h→u∗′(1)(12−uout4)=0.3085R_{N-1}/h\to u^{*\prime}(1)\bigl(\tfrac12-\tfrac{u_{\rm out}}4\bigr)=0.3085(N=4096N=4096 的实测:−0.8284 与 0.3071)。所以光滑限制器在细网格上的两个边界行是 O(h)O(h),而内部行是 O(h2)O(h^2);这是对极限情形的推导加实测,不是定理。

The first-order scheme has no such difference: every face has ζf=−h u∗′+O(h2)\zeta_f=-h\,u^{*\prime}+O(h^2), so every interior row, rows 11 and N−1N-1 included, is Rj=−h2u∗′′(xj)+O(h3)R_j=-h^2u^{*\prime\prime}(x_j)+O(h^3). At N=4096N=4096 the largest interior row divided by h2h^2 is 7.8957 (max⁡∣u∗′′∣=4π2a=7.8957\max|u^{*\prime\prime}|=4\pi^2a=7.8957) and row 11 gives −3.3517 (−u∗′′(0)=−3.3618-u^{*\prime\prime}(0)=-3.3618). The smooth limiter has one peculiarity on fine meshes: ϵ=0.01\epsilon=0.01 is fixed, the two differences of an interior slope, lj,rj≈h ux∗≪ϵl_j,r_j\approx h\,u^*_x\ll\epsilon, make the limiter squeeze the interior slopes to almost zero, so the interior faces behave like first-order faces; the boundary slopes are one-sided and unlimited and are not squeezed, so the boundary faces still behave like second-order faces with a slope. The face errors then differ by O(h)O(h): R1/h→−u∗′(0)(12+uin4)=−0.8286R_1/h\to-u^{*\prime}(0)\bigl(\tfrac12+\tfrac{u_{\rm in}}4\bigr)=-0.8286 and RN−1/h→u∗′(1)(12−uout4)=0.3085R_{N-1}/h\to u^{*\prime}(1)\bigl(\tfrac12-\tfrac{u_{\rm out}}4\bigr)=0.3085 (measured at N=4096N=4096: −0.8284 and 0.3071). So with the smooth limiter on fine meshes the two boundary rows are O(h)O(h) and the interior rows O(h2)O(h^2); this is a derivation of the limiting case plus measurement, not a theorem.

图 19 · 沿节点的截断误差:残差密度 |R_j(u*)|/h(对数轴),N=64,默认设计。无限制器线性(蓝色空心):第 2,…,N-2 行最大 1.7e−3,紧邻边界的两行更大(|R_1|/h=1.8 × 10^(-2),|R_(N-1)|/h=6.3 × 10^(-3))。一阶(灰):最大 1.2e−1,边界行与内部行没有区别。光滑限制器(橙):内部最大 1.2e−1,边界行 |R_1|/h=1.3 × 10^(-1) 已经是所有行里最大的(内部行的中位数是 9 × 10^(-3))。第 0 行与第 N 行恒为零,没有画出。10-7​10-6​10-5​10-4​10-3​10-2​10-1​100.20.40.60.81节点 xj​(N = 64;行 0 与行 N 恒为零,未画出)|Rj​(u*)|/h一阶无限制器线性光滑限制器
图 19 · 沿节点的截断误差:残差密度 ∣Rj(𝐮∗)∣/h|R_j(\mathbf u^*)|/h(对数轴),N=64N=64,默认设计。无限制器线性(蓝色空心):第 2,…,N−22,\dots,N-2 行最大 1.7e−3,紧邻边界的两行更大(∣R1∣/h=1.8×10−2|R_1|/h=1.8\times10^{-2},∣RN−1∣/h=6.3×10−3|R_{N-1}|/h=6.3\times10^{-3})。一阶(灰):最大 1.2e−1,边界行与内部行没有区别。光滑限制器(橙):内部最大 1.2e−1,边界行 ∣R1∣/h=1.3×10−1|R_1|/h=1.3\times10^{-1} 已经是所有行里最大的(内部行的中位数是 9×10−39\times10^{-3})。第 00 行与第 NN 行恒为零,没有画出。
Figure 19 · The truncation error along the nodes: the residual density |R_j(u*)|/h (logarithmic axis), N=64, default design. Unlimited linear (blue rings): at most 1.7e−3 in rows 2,…,N-2, the two rows next to the boundary are larger (|R_1|/h=1.8 × 10^(-2), |R_(N-1)|/h=6.3 × 10^(-3)). First order (grey): at most 1.2e−1, and the boundary rows do not stand out. Smooth limiter (orange): 1.2e−1 inside, with |R_1|/h=1.3 × 10^(-1) already the largest of all rows (the median interior row is 9 × 10^(-3)). Rows 0 and N vanish and are not drawn.10-7​10-6​10-5​10-4​10-3​10-2​10-1​100.20.40.60.81node xj​ (N = 64; rows 0 and N vanish and are not drawn)|Rj​(u*)|/hfirst orderunlimited linearsmooth limiter
Figure 19 · The truncation error along the nodes: the residual density ∣Rj(𝐮∗)∣/h|R_j(\mathbf u^*)|/h (logarithmic axis), N=64N=64, default design. Unlimited linear (blue rings): at most 1.7e−3 in rows 2,…,N−22,\dots,N-2, the two rows next to the boundary are larger (∣R1∣/h=1.8×10−2|R_1|/h=1.8\times10^{-2}, ∣RN−1∣/h=6.3×10−3|R_{N-1}|/h=6.3\times10^{-3}). First order (grey): at most 1.2e−1, and the boundary rows do not stand out. Smooth limiter (orange): 1.2e−1 inside, with ∣R1∣/h=1.3×10−1|R_1|/h=1.3\times10^{-1} already the largest of all rows (the median interior row is 9×10−39\times10^{-3}). Rows 00 and NN vanish and are not drawn.
图 20 · 精确节点值上的残差与解的误差随 N(8 到 4096,默认设计)。前三个图:第 1 行、第 N-1 行和第 2,…,N-2 行的最大值,虚线是 h,h^2,h^3 的参考斜率。无限制器线性:内部行按 h^3 下降(最后一次加密的观测阶 3.00),第 1 行与第 N-1 行按 h^2 下降(2.00 与 2.00);一阶:所有行按 h^2 下降(内部 2.00,第 1 行 2.00);光滑限制器:内部行最后按 h^2 下降(2.00),两个边界行按 h(1.00 与 0.99)。第四个图:解的误差 ‖U-u*‖_∞,最后一次加密的观测阶:无限制器线性 1.98,一阶 1.00,光滑限制器 0.98。10-11​10-9​10-7​10-5​10-3​10-1​101001000N|Rj​(u*)|hh²h³无限制器线性行 1行 N−1行 2 … N−2 的最大值10-11​10-9​10-7​10-5​10-3​10-1​101001000N|Rj​(u*)|hh²h³一阶行 1行 N−1行 2 … N−2 的最大值10-11​10-9​10-7​10-5​10-3​10-1​101001000N|Rj​(u*)|hh²h³光滑限制器行 1行 N−1行 2 … N−2 的最大值10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​1101001000N‖U − u*‖∞hh²解的误差一阶无限制器线性光滑限制器
图 20 · 精确节点值上的残差与解的误差随 NN(88 到 4096,默认设计)。前三个图:第 11 行、第 N−1N-1 行和第 2,…,N−22,\dots,N-2 行的最大值,虚线是 h,h2,h3h,h^2,h^3 的参考斜率。无限制器线性:内部行按 h3h^3 下降(最后一次加密的观测阶 3.00),第 11 行与第 N−1N-1 行按 h2h^2 下降(2.00 与 2.00);一阶:所有行按 h2h^2 下降(内部 2.00,第 11 行 2.00);光滑限制器:内部行最后按 h2h^2 下降(2.00),两个边界行按 hh(1.00 与 0.99)。第四个图:解的误差 ∥𝐔−𝐮∗∥∞\|\mathbf U-\mathbf u^*\|_\infty,最后一次加密的观测阶:无限制器线性 1.98,一阶 1.00,光滑限制器 0.98。
Figure 20 · The residual at the exact nodal values and the error of the solution against N (8 to 4096, default design). First three panels: row 1, row N-1 and the largest of rows 2,…,N-2; dashed reference lines of slope h,h^2,h^3. Unlimited linear: the interior rows fall like h^3 (observed order 3.00 over the last doubling), rows 1 and N-1 like h^2 (2.00 and 2.00); first order: all rows like h^2 (interior 2.00, row 1 2.00); smooth limiter: the interior rows finally like h^2 (2.00), the two boundary rows like h (1.00 and 0.99). Fourth panel: the error of the solution ‖U-u*‖_∞; observed order over the last doubling: 1.98 for unlimited linear, 1.00 for first order and 0.98 for the smooth limiter.10-11​10-9​10-7​10-5​10-3​10-1​101001000N|Rj​(u*)|hh²h³unlimited linearrow 1row N−1largest of rows 2 … N−210-11​10-9​10-7​10-5​10-3​10-1​101001000N|Rj​(u*)|hh²h³first orderrow 1row N−1largest of rows 2 … N−210-11​10-9​10-7​10-5​10-3​10-1​101001000N|Rj​(u*)|hh²h³smooth limiterrow 1row N−1largest of rows 2 … N−210-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​1101001000N‖U − u*‖∞hh²error of the solutionfirst orderunlimited linearsmooth limiter
Figure 20 · The residual at the exact nodal values and the error of the solution against NN (88 to 4096, default design). First three panels: row 11, row N−1N-1 and the largest of rows 2,…,N−22,\dots,N-2; dashed reference lines of slope h,h2,h3h,h^2,h^3. Unlimited linear: the interior rows fall like h3h^3 (observed order 3.00 over the last doubling), rows 11 and N−1N-1 like h2h^2 (2.00 and 2.00); first order: all rows like h2h^2 (interior 2.00, row 11 2.00); smooth limiter: the interior rows finally like h2h^2 (2.00), the two boundary rows like hh (1.00 and 0.99). Fourth panel: the error of the solution ∥𝐔−𝐮∗∥∞\|\mathbf U-\mathbf u^*\|_\infty; observed order over the last doubling: 1.98 for unlimited linear, 1.00 for first order and 0.98 for the smooth limiter.

为什么边界行不会拖累精度阶

Why the boundary rows do not drag the order down

通量常数。R(𝐔,D)=0R(\mathbf U,D)=0 的第 1,…,N−11,\dots,N-1 行说 Hj−Qj=Hj−1−Qj−1H_j-Q_j=H_{j-1}-Q_{j-1}:面上的通量失配在全部 NN 个面上是同一个常数。

The flux constant. Rows 1,…,N−11,\dots,N-1 of R(𝐔,D)=0R(\mathbf U,D)=0 say Hj−Qj=Hj−1−Qj−1H_j-Q_j=H_{j-1}-Q_{j-1}: the flux mismatch of a face is the same constant on all NN faces.

R1=⋯=RN−1=0  ⟺  Hf(𝐔)=Qf+cH(f=0,…,N−1).R_1=\dots=R_{N-1}=0\iff H_f(\mathbf U)=Q_f+c_H\quad(f=0,\dots,N-1).

cHc_H 是一个常数(下标 H 表示通量,与第 3 节的偏导 cL,cRc_L,c_R 无关)。N−1N-1 个方程确定 N−1N-1 个内部未知量,cHc_H 是离散问题多出来的那一个常数:数值解携带的是精确通量加一个常数(第 5 节再回到这一点)。默认设计(N=8N=8):无限制器线性的 cHc_H 是 −4.81e−3,一阶是 −1.24e−1,光滑限制器是 3.08e−4(各面的失配与它相差不超过 10−1210^{-12})。加密时 cH→0c_H\to0,但并不单调:无限制器线性的 cHc_H 变号 2 次,在 N=8N=8 与 N=16N=16 之间(−4.8e−3 到 1.6e−3)、在 N=256N=256 与 N=512N=512 之间(4.9e−7 到 −4.8e−7),N=4096N=4096 时是 −1.7e−8。所以在格点格式里,cHc_H 不是决定误差大小的量。

cHc_H is one constant (the subscript H stands for the flux; it has nothing to do with the partial derivatives cL,cRc_L,c_R of Section 3). N−1N-1 equations fix the N−1N-1 interior unknowns, and cHc_H is the one constant the discrete problem leaves over: the numerical solution carries the exact flux plus a constant (Section 5 returns to this). At the defaults (N=8N=8): cHc_H is −4.81e−3 for unlimited linear, −1.24e−1 for first order and 3.08e−4 for the smooth limiter (the mismatch of every face is within 10−1210^{-12} of it). Under refinement cH→0c_H\to0, but not monotonically: for unlimited linear it changes sign twice, between N=8N=8 and N=16N=16 (−4.8e−3 to 1.6e−3) and between N=256N=256 and N=512N=512 (4.9e−7 to −4.8e−7), and is −1.7e−8 at N=4096N=4096. So on the node mesh cHc_H is not what sets the size of the error.

误差方程。设 e=𝐔−𝐮∗e=\mathbf U-\mathbf u^*。两个约束行都精确满足,所以 e0=eN=0e_0=e_N=0;所有面上 Hf(𝐔)−Hf(𝐮∗)=cH−ζfH_f(\mathbf U)-H_f(\mathbf u^*)=c_H-\zeta_f:误差引起的通量增量,等于面误差取负号再加常数 cHc_H。对一阶和无限制器线性重构,RR 是 𝐔\mathbf U 的二次多项式(第 5 节),而二次函数的割线 Jacobian 就是它在中点的 Jacobian,所以精确地有 R(𝐔)−R(𝐮∗)=A(𝐮mid) eR(\mathbf U)-R(\mathbf u^*)=A(\mathbf u_{\rm mid})\,e,其中 𝐮mid=12(𝐔+𝐮∗)\mathbf u_{\rm mid}=\tfrac12(\mathbf U+\mathbf u^*)。取第 1,…,N−11,\dots,N-1 行(R(𝐔)=0R(\mathbf U)=0,e0=eN=0e_0=e_N=0):

The error equation. Let e=𝐔−𝐮∗e=\mathbf U-\mathbf u^*. Both constraint rows hold exactly, so e0=eN=0e_0=e_N=0, and on every face Hf(𝐔)−Hf(𝐮∗)=cH−ζfH_f(\mathbf U)-H_f(\mathbf u^*)=c_H-\zeta_f: the flux increments caused by the error are the face errors with the sign changed, plus the constant cHc_H. For first order and unlimited linear reconstruction RR is a quadratic polynomial in 𝐔\mathbf U (Section 5), and the secant Jacobian of a quadratic function is its Jacobian at the midpoint, so exactly R(𝐔)−R(𝐮∗)=A(𝐮mid) eR(\mathbf U)-R(\mathbf u^*)=A(\mathbf u_{\rm mid})\,e with 𝐮mid=12(𝐔+𝐮∗)\mathbf u_{\rm mid}=\tfrac12(\mathbf U+\mathbf u^*). Taking rows 1,…,N−11,\dots,N-1 (R(𝐔)=0R(\mathbf U)=0, e0=eN=0e_0=e_N=0):

AII(𝐮mid) eI=−RI(𝐮∗),(RI(𝐮∗))j=ζj−ζj−1(1≤j≤N−1).A_{\rm II}(\mathbf u_{\rm mid})\,e_{\rm I}=-R_{\rm I}(\mathbf u^*),\qquad\bigl(R_{\rm I}(\mathbf u^*)\bigr)_j=\zeta_j-\zeta_{j-1}\quad(1\le j\le N-1).

这是恒等式,不是近似(一阶与无限制器线性):实测 N=8N=8 到 1024,由它解出的 ee 与实际的 𝐔−𝐮∗\mathbf U-\mathbf u^* 之差不超过 10−1210^{-12}。光滑限制器的残差不是多项式,没有这个恒等式。把 AII−1A_{\rm II}^{-1} 记作 GG(在 1,…,N−11,\dots,N-1 之外取零),逐行写开,节点 ii 的误差是各面误差的加权和,权是 GG 相邻元素之差:

This is an identity, not an approximation (first order and unlimited linear): measured for N=8N=8 to 1024, the ee it determines differs from the actual 𝐔−𝐮∗\mathbf U-\mathbf u^* by at most 10−1210^{-12}. The residual of the smooth limiter is no polynomial and has no such identity. Writing GG for AII−1A_{\rm II}^{-1} (zero outside 1,…,N−11,\dots,N-1) and spelling the system out, the error at node ii is a weighted sum of the face errors, with weights the differences of neighbouring entries of GG:

ei=−∑f=0N−1(Gi,f−Gi,f+1) ζf,∥e∥∞≤KN max⁡f∣ζf∣,KN=max⁡i∑f=0N−1∣Gi,f−Gi,f+1∣.e_i=-\sum_{f=0}^{N-1}\bigl(G_{i,f}-G_{i,f+1}\bigr)\,\zeta_f,\qquad\|e\|_\infty\le K_N\,\max_f|\zeta_f|,\qquad K_N=\max_i\sum_{f=0}^{N-1}\bigl|G_{i,f}-G_{i,f+1}\bigr|.

KNK_N 只由矩阵决定:它是 AII−1A_{\rm II}^{-1} 与“相邻面误差之差”这个差分算子的复合在最大范数下的范数。误差由面误差本身控制,而不是由行的截断误差控制:行的截断误差是面误差的差,差分算子把它变小了一阶,而 AII−1A_{\rm II}^{-1} 把这一阶还给了它。

KNK_N depends on the matrix only: it is the max-norm of AII−1A_{\rm II}^{-1} composed with the difference of neighbouring face errors. The error is controlled by the face errors themselves, not by the truncation errors of the rows: the truncation error of a row is a difference of face errors, which makes it one power of hh smaller, and AII−1A_{\rm II}^{-1} gives that power back.

紧邻边界的节点。面 00 读 U0,U1,U2U_0,U_1,U_2,e0=0e_0=0,所以它的关系只含 e1,e2e_1,e_2(同样是精确的,用中点状态 𝐮mid\mathbf u_{\rm mid} 上的 cLmid,cRmidc_L^{\rm mid},c_R^{\rm mid})。一阶重构时只含 e1e_1:

The node next to the boundary. Face 00 reads U0,U1,U2U_0,U_1,U_2 and e0=0e_0=0, so its relation contains e1,e2e_1,e_2 only (again exact, with cLmid,cRmidc_L^{\rm mid},c_R^{\rm mid} at the midpoint state 𝐮mid\mathbf u_{\rm mid}). At first order it contains e1e_1 only:

一阶: (cRmid−νh)e1=cH−ζ0,e1=ζ0−cH1−12umid,1+ν/h;无限制器线性: (12cLmid+cRmid−νh)e1−14cRmid e2=cH−ζ0.\text{一阶:}\ \bigl(c_R^{\rm mid}-\tfrac\nu h\bigr)e_1=c_H-\zeta_0,\quad e_1=\frac{\zeta_0-c_H}{1-\tfrac12u_{{\rm mid},1}+\nu/h};\qquad\text{无限制器线性:}\ \bigl(\tfrac12c_L^{\rm mid}+c_R^{\rm mid}-\tfrac\nu h\bigr)e_1-\tfrac14c_R^{\rm mid}\,e_2=c_H-\zeta_0.
first order:  (cRmid−νh)e1=cH−ζ0,e1=ζ0−cH1−12umid,1+ν/h;unlimited linear:  (12cLmid+cRmid−νh)e1−14cRmid e2=cH−ζ0.\text{first order: }\ \bigl(c_R^{\rm mid}-\tfrac\nu h\bigr)e_1=c_H-\zeta_0,\quad e_1=\frac{\zeta_0-c_H}{1-\tfrac12u_{{\rm mid},1}+\nu/h};\qquad\text{unlimited linear: }\ \bigl(\tfrac12c_L^{\rm mid}+c_R^{\rm mid}-\tfrac\nu h\bigr)e_1-\tfrac14c_R^{\rm mid}\,e_2=c_H-\zeta_0.

这是格心页“除以一个大分母”论证的节点版本:面误差 ζ0−cH\zeta_0-c_H 除以一个随 ν/h\nu/h 增大的分母。h≪νh\ll\nu 时分母约为 −ν/h-\nu/h,于是 e1≈h(ζ0−cH)/ν=O(h3/ν)e_1\approx h(\zeta_0-c_H)/\nu=O(h^3/\nu):紧邻边界的节点特别准。N=4096N=4096 时 e1e_1 是 1.679e−9,而 h(ζ0−cH)/νh(\zeta_0-c_H)/\nu 是 1.666e−9(比值 1.0078)。两个关系式对 N=8N=8 到 4096 都精确成立(两边之差不超过 2×10−132\times10^{-13})。但它不是精度阶的来源:在 ν/h\nu/h 小的粗网格上(N=8N=8 时 ν/h\nu/h 只有 0.08),e1e_1 是 2.39e−3,并不比别的节点大(∥e∥∞\|e\|_\infty 是 2.78e−2)。整体误差由稳定性决定。

This is the node version of the “division by a large denominator” of the cell-centred page: the face error ζ0−cH\zeta_0-c_H is divided by a denominator that grows with ν/h\nu/h. For h≪νh\ll\nu the denominator is about −ν/h-\nu/h, so e1≈h(ζ0−cH)/ν=O(h3/ν)e_1\approx h(\zeta_0-c_H)/\nu=O(h^3/\nu): the node next to the boundary is particularly accurate. At N=4096N=4096, e1e_1 is 1.679e−9 while h(ζ0−cH)/νh(\zeta_0-c_H)/\nu is 1.666e−9 (ratio 1.0078). Both relations hold exactly for N=8N=8 to 4096 (the two sides differ by at most 2×10−132\times10^{-13}). But it is not the source of the order: on a coarse mesh with small ν/h\nu/h (ν/h\nu/h is only 0.08 at N=8N=8) one finds e1e_1 equal to 2.39e−3, which is no larger than the errors elsewhere (∥e∥∞\|e\|_\infty is 2.78e−2). The error of the whole solution is set by stability.

稳定性:一阶格式的证明。设 𝐔\mathbf U 是 R=0R=0 的位于 Newton 范围 0.1<U<1.90.1<U<1.9 内的解(所有算出的解都是)。因为默认设计里 u∗≥1−a=0.8u^*\ge1-a=0.8 且 u∗≤1+a=1.2u^*\le1+a=1.2,所以 0.45<umid<1.550.45<u_{\rm mid}<1.55,于是对任何 hh 都有 αf,βf>0\alpha_f,\beta_f>0 且 μf>0.45\mu_f>0.45。一阶重构时每个面有 Hf(𝐔)−Hf(𝐮∗)=αfef−βfef+1H_f(\mathbf U)-H_f(\mathbf u^*)=\alpha_fe_f-\beta_fe_{f+1},其中 αf=1+νh+12umid,f\alpha_f=1+\tfrac\nu h+\tfrac12u_{{\rm mid},f},βf=1+νh−12umid,f+1\beta_f=1+\tfrac\nu h-\tfrac12u_{{\rm mid},f+1},且 αf−βf=μf=12(umid,f+umid,f+1)\alpha_f-\beta_f=\mu_f=\tfrac12(u_{{\rm mid},f}+u_{{\rm mid},f+1})。于是 αfef−βfef+1=cH−ζf\alpha_fe_f-\beta_fe_{f+1}=c_H-\zeta_f。从出口向入口解(eN=0e_N=0):

Stability: a proof at first order. Let 𝐔\mathbf U be a solution of R=0R=0 inside Newton's box 0.1<U<1.90.1<U<1.9 (all computed solutions are). At the default design u∗≥1−a=0.8u^*\ge1-a=0.8 and u∗≤1+a=1.2u^*\le1+a=1.2, which gives 0.45<umid<1.550.45<u_{\rm mid}<1.55, so αf,βf>0\alpha_f,\beta_f>0 and μf>0.45\mu_f>0.45 for every hh. At first order every face has Hf(𝐔)−Hf(𝐮∗)=αfef−βfef+1H_f(\mathbf U)-H_f(\mathbf u^*)=\alpha_fe_f-\beta_fe_{f+1} with αf=1+νh+12umid,f\alpha_f=1+\tfrac\nu h+\tfrac12u_{{\rm mid},f} and βf=1+νh−12umid,f+1\beta_f=1+\tfrac\nu h-\tfrac12u_{{\rm mid},f+1}, and αf−βf=μf=12(umid,f+umid,f+1)\alpha_f-\beta_f=\mu_f=\tfrac12(u_{{\rm mid},f}+u_{{\rm mid},f+1}). So αfef−βfef+1=cH−ζf\alpha_fe_f-\beta_fe_{f+1}=c_H-\zeta_f. Solving from the outlet (eN=0e_N=0) towards the inlet:

ef=∑g=fN−1(∏k=fg−1βkαk)cH−ζgαg.e_f=\sum_{g=f}^{N-1}\Bigl(\prod_{k=f}^{g-1}\frac{\beta_k}{\alpha_k}\Bigr)\frac{c_H-\zeta_g}{\alpha_g}.

所有的权都是正的。在 f=0f=0 处,入口条件 e0=0e_0=0 表明 cHc_H 是各 ζg\zeta_g 的加权平均(权为正),所以 ∣cH∣≤max⁡f∣ζf∣|c_H|\le\max_f|\zeta_f|,∣cH−ζg∣≤2max⁡f∣ζf∣|c_H-\zeta_g|\le2\max_f|\zeta_f|。权之和 Sf=∑g≥f(∏k=fg−1βk/αk)/αgS_f=\sum_{g\ge f}\bigl(\prod_{k=f}^{g-1}\beta_k/\alpha_k\bigr)/\alpha_g 满足 Sf=1/αf+(βf/αf)Sf+1S_f=1/\alpha_f+(\beta_f/\alpha_f)S_{f+1},从 SN−1=1/αN−1≤1/μmin⁡S_{N-1}=1/\alpha_{N-1}\le1/\mu_{\min} 起归纳(μmin⁡=min⁡fμf\mu_{\min}=\min_f\mu_f):

All weights are positive. At f=0f=0 the inlet condition e0=0e_0=0 says that cHc_H is a weighted mean of the ζg\zeta_g with positive weights, so ∣cH∣≤max⁡f∣ζf∣|c_H|\le\max_f|\zeta_f| and ∣cH−ζg∣≤2max⁡f∣ζf∣|c_H-\zeta_g|\le2\max_f|\zeta_f|. The sum of the weights Sf=∑g≥f(∏k=fg−1βk/αk)/αgS_f=\sum_{g\ge f}\bigl(\prod_{k=f}^{g-1}\beta_k/\alpha_k\bigr)/\alpha_g satisfies Sf=1/αf+(βf/αf)Sf+1S_f=1/\alpha_f+(\beta_f/\alpha_f)S_{f+1}, and induction from SN−1=1/αN−1≤1/μmin⁡S_{N-1}=1/\alpha_{N-1}\le1/\mu_{\min} gives (with μmin⁡=min⁡fμf\mu_{\min}=\min_f\mu_f):

Sf≤1αf+βfαfμmin⁡≤μf+βfαfμmin⁡=1μmin⁡.S_f\le\frac1{\alpha_f}+\frac{\beta_f}{\alpha_f\mu_{\min}}\le\frac{\mu_f+\beta_f}{\alpha_f\mu_{\min}}=\frac1{\mu_{\min}}.

于是 ∣ef∣≤2max⁡g∣ζg∣ Sf|e_f|\le2\max_g|\zeta_g|\,S_f,即

Hence ∣ef∣≤2max⁡g∣ζg∣ Sf|e_f|\le2\max_g|\zeta_g|\,S_f, that is

∥𝐔−𝐮∗∥∞≤2μmin⁡ max⁡f∣ζf∣(一阶)。\|\mathbf U-\mathbf u^*\|_\infty\le\frac2{\mu_{\min}}\,\max_f|\zeta_f|\qquad\text{(一阶)。}
∥𝐔−𝐮∗∥∞≤2μmin⁡ max⁡f∣ζf∣(first order).\|\mathbf U-\mathbf u^*\|_\infty\le\frac2{\mu_{\min}}\,\max_f|\zeta_f|\qquad\text{(first order).}

这里完全没有用到边界的任何特殊之处,只用了 e0=eN=0e_0=e_N=0:一阶格式的 ζf=−h u∗′+O(h2)\zeta_f=-h\,u^{*\prime}+O(h^2) 在所有面上成立,所以解的误差是 O(h)O(h)。数值检验:N=8N=8 到 1024,所有的权为正(最小的权也大于零),加权平均给出的 cHc_H 与面通量失配的平均相差不超过 2×10−132\times10^{-13},证明里的上界 2max⁡∣ζ∣/μmin⁡2\max|\zeta|/\mu_{\min} 成立:0.2718 对 0.3953(N=8N=8),2.46e−3 对 3.07e−3(N=1024N=1024);μmin⁡\mu_{\min} 在 0.7741 到 0.7994 之间,接近 min⁡u∗=0.80\min u^*=0.80,所以常数 2/μmin⁡2/\mu_{\min} 约为 2.502 到 2.584;对任何 hh 它都小于 2/0.45=4.4442/0.45=4.444(算出的解的 umidu_{\rm mid} 在 0.77 与 1.20 之间)。

Nothing special about the boundary was used, only e0=eN=0e_0=e_N=0: at first order ζf=−h u∗′+O(h2)\zeta_f=-h\,u^{*\prime}+O(h^2) holds on every face, so the error of the solution is O(h)O(h). Numerical check, N=8N=8 to 1024: all weights are positive (the smallest is still above zero), the cHc_H given by the weighted mean differs from the mean face mismatch by at most 2×10−132\times10^{-13}, and the bound 2max⁡∣ζ∣/μmin⁡2\max|\zeta|/\mu_{\min} of the proof holds: 0.2718 against 0.3953 (N=8N=8), 2.46e−3 against 3.07e−3 (N=1024N=1024); μmin⁡\mu_{\min} lies between 0.7741 and 0.7994, close to min⁡u∗=0.80\min u^*=0.80, so the constant 2/μmin⁡2/\mu_{\min} is about 2.502 to 2.584; for every hh it is below 2/0.45=4.4442/0.45=4.444 (the umidu_{\rm mid} of the computed solutions lies between 0.77 and 1.20).

稳定性:无限制器线性只是数值观察。五对角矩阵没有这种符号结构(第 6 节),上面的证明不适用,KNK_N 要直接算。实测(精确逆矩阵,N=8N=8 到 1024):KNK_N 对一阶(至多 2.517)、无限制器线性(至多 3.429)和光滑限制器(在解处线性化,至多 3.568)都有界,并且都趋于约 2.502.50,也就是 2/min⁡u∗=2/(1−a)=2.502/\min u^*=2/(1-a)=2.50(无限制器线性:N=1024N=1024 时 2.4981;一阶 2.4997)。KNK_N 有界与 ζf=O(h2)\zeta_f=O(h^2) 在所有 NN 个面上成立(上面的展开)合在一起,给出无限制器线性的 ∥e∥∞=O(h2)\|e\|_\infty=O(h^2):展开是推导,KNK_N 有界是实测,不是定理。下表是无限制器线性的几个 NN。

Stability: an observation for unlimited linear. The five-diagonal matrix has no such sign structure (Section 6), the proof above does not apply, and KNK_N has to be computed. Measured (exact inverse, N=8N=8 to 1024): KNK_N is bounded for first order (at most 2.517), unlimited linear (at most 3.429) and the smooth limiter (linearised at the solution, at most 3.568), and tends to about 2.502.50 in all three, the value 2/min⁡u∗=2/(1−a)=2.502/\min u^*=2/(1-a)=2.50 (unlimited linear: 2.4981 at N=1024N=1024; first order 2.4997). A bounded KNK_N together with ζf=O(h2)\zeta_f=O(h^2) on all NN faces (the expansions above) gives ∥e∥∞=O(h2)\|e\|_\infty=O(h^2) for unlimited linear: the expansions are a derivation, the boundedness of KNK_N is a measurement, not a theorem. The table lists a few NN for unlimited linear.

NNmax⁡f∣ζf∣\max_f|\zeta_f|ζ0\zeta_0ζN−1\zeta_{N-1}cHc_He1e_1∥𝐔−𝐮∗∥∞\|\mathbf U-\mathbf u^*\|_\inftyKNmax⁡f∣ζf∣K_N\max_f|\zeta_f|
82.94e−2−3.95e−3−2.94e−2−4.81e−32.39e−32.78e−21.01e−1
321.19e−35.67e−4−1.19e−35.82e−48.18e−41.79e−33.32e−3
1287.23e−54.83e−5−5.66e−51.6e−53.42e−58.02e−51.81e−4
5124.52e−63.21e−6−3.24e−6−4.8e−77.7e−74.16e−61.13e−5
图 21 · 误差由什么控制(默认设计)。左(无限制器线性):全部 N 个面上的最大面误差(橙),解的误差 ‖U-u*‖_∞(紫)和它的上界 K_Nmax|ζ_f|(灰虚线,N ≤ 1024);三者按 h^2 下降。右:三种重构的稳定常数 K_N(一阶与无限制器线性取中点状态的矩阵,光滑限制器取解处的矩阵),虚线是 2/min u*。10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​101001000Nh²无限制器线性maxf​ |ζf​|(全部 N 个面)KN​ maxf​ |ζf​|‖U − u*‖∞22.533.54101001000NKN​2/min u* = 2.500稳定常数 KN​一阶无限制器线性光滑限制器
图 21 · 误差由什么控制(默认设计)。左(无限制器线性):全部 NN 个面上的最大面误差(橙),解的误差 ∥𝐔−𝐮∗∥∞\|\mathbf U-\mathbf u^*\|_\infty(紫)和它的上界 KNmax⁡∣ζf∣K_N\max|\zeta_f|(灰虚线,N≤1024N\le1024);三者按 h2h^2 下降。右:三种重构的稳定常数 KNK_N(一阶与无限制器线性取中点状态的矩阵,光滑限制器取解处的矩阵),虚线是 2/min⁡u∗2/\min u^*。
Figure 21 · What controls the error (default design). Left (unlimited linear): the largest face error over all N faces (orange), the error of the solution ‖U-u*‖_∞ (violet) and its bound K_Nmax|ζ_f| (grey dashed, N ≤ 1024); all three fall like h^2. Right: the stability constant K_N of the three reconstructions (the matrix at the midpoint state for first order and unlimited linear, at the solution for the smooth limiter), the dashed line is 2/min u*.10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​101001000Nh²unlimited linearmaxf​ |ζf​| (all N faces)KN​ maxf​ |ζf​|‖U − u*‖∞22.533.54101001000NKN​2/min u* = 2.500stability constant KN​first orderunlimited linearsmooth limiter
Figure 21 · What controls the error (default design). Left (unlimited linear): the largest face error over all NN faces (orange), the error of the solution ∥𝐔−𝐮∗∥∞\|\mathbf U-\mathbf u^*\|_\infty (violet) and its bound KNmax⁡∣ζf∣K_N\max|\zeta_f| (grey dashed, N≤1024N\le1024); all three fall like h2h^2. Right: the stability constant KNK_N of the three reconstructions (the matrix at the midpoint state for first order and unlimited linear, at the solution for the smooth limiter), the dashed line is 2/min⁡u∗2/\min u^*.

下面的面板把整件事摆在一起:选择 NN 与重构,看面误差 ζf\zeta_f、常数 cHc_H、实际误差 ee、由 −AII−1(ζj−ζj−1)j-A_{\rm II}^{-1}(\zeta_j-\zeta_{j-1})_j 算出的线性响应,以及上界 KNmax⁡∣ζf∣K_N\max|\zeta_f|;一阶还给出证明里的 2max⁡∣ζ∣/μmin⁡2\max|\zeta|/\mu_{\min}。

The panel below puts it all together: choose NN and the reconstruction and see the face errors ζf\zeta_f, the constant cHc_H, the actual error ee, the linear response computed from −AII−1(ζj−ζj−1)j-A_{\rm II}^{-1}(\zeta_j-\zeta_{j-1})_j, and the bound KNmax⁡∣ζf∣K_N\max|\zeta_f|; at first order it also shows the 2max⁡∣ζ∣/μmin⁡2\max|\zeta|/\mu_{\min} of the proof.

光滑限制器。KNK_N 同样有界,但 ϵ=0.01\epsilon=0.01 固定,限制器在细网格上把内部斜率压掉,内部面误差只剩一阶(上面的 R1/hR_1/h 与内部行说明了同一件事),解的误差也就是一阶:N=64,128,256N=64,128,256 时 ∥𝐔−𝐮∗∥∞\|\mathbf U-\mathbf u^*\|_\infty 是 5.03e−3、6.5e−3、6.27e−3,几乎不下降,只有 N≥512N\ge512 才随 hh 一阶下降(最后三次加密的观测阶:0.85、0.95、0.98)。固定 ϵ\epsilon 时,光滑限制器在细网格上不是二阶格式。

The smooth limiter. KNK_N is bounded here too, but ϵ=0.01\epsilon=0.01 is fixed, the limiter squeezes the interior slopes on fine meshes, the interior face errors are only first order (the R1/hR_1/h and interior rows above say the same), and so is the error of the solution: ∥𝐔−𝐮∗∥∞\|\mathbf U-\mathbf u^*\|_\infty is 5.03e−3, 6.5e−3 and 6.27e−3 at N=64,128,256N=64,128,256, hardly falling, and only from N≥512N\ge512 does it fall like hh (observed orders of the last three doublings: 0.85, 0.95, 0.98). With ϵ\epsilon fixed, the smooth limiter is not a second-order scheme on fine meshes.

与格心页对照。格心页同一个实验里(除另有说明外都是无限制器线性重构),两个边界面通量只有一阶(半格差商 O(h)O(h),端单元不重构):ζ0=O(h)\zeta_0=O(h),第 00 行与第 11 行的残差密度趋于常数(N=4096N=4096 时 R0/h=−0.5093R_0/h=-0.5093,R1/h=0.8289R_1/h=0.8289),解的误差靠“面误差除以一个与 2ν/h2\nu/h 有关的分母”和 cHc_H 来控制,N≤256N\le256 时相邻两次加密的观测阶只在 1.15 到 1.52 之间,直到 N≳1000N\gtrsim1000 才接近 2。对无限制器线性,格点格式里全部 NN 个面的误差都是 O(h2)O(h^2),所有行的残差密度都趋于零,解的误差从粗网格起就是二阶:相邻两次加密的观测阶,N=8→16N=8\to16 起是 1.83 到 2.36(N=2048→4096N=2048\to4096:1.98)。同一网格上,对无限制器线性,格点格式的 ∥𝐔−𝐮∗∥∞\|\mathbf U-\mathbf u^*\|_\infty 比格心格式的 ∥𝐔−⟨u∗⟩∥∞\|\mathbf U-\langle u^*\rangle\|_\infty 小得多:N=8N=8 时 2.78e−2 对 9.21e−2(3.3 倍),N=64N=64 时 3.95e−4 对 8e−3(20.2 倍),N=4096N=4096 时 7.31e−8 对 6.59e−6(90 倍)。这只对无限制器线性成立:一阶时格点格式在每个 NN 上的误差都更大(N=8N=8 时 2.72e−1 对 1.93e−1,N=4096N=4096 时 6.15e−4 对 6.13e−4);光滑限制器的优势(N=8N=8 时 3.2 倍)到 N=1024N=1024 时只剩 1.02 倍。(两个格式的未知量不同:格心的是单元平均,节点的是点值;二者各自对照自己的精确参考,比较的是各自的离散误差。)

Against the cell-centred page. In the same experiment on the cell-centred page (unlimited linear reconstruction unless another is named) the two end-face fluxes are only first order (the half-cell quotient is O(h)O(h) and the end cells are not reconstructed): ζ0=O(h)\zeta_0=O(h), the residual densities of rows 00 and 11 tend to constants (R0/h=−0.5093R_0/h=-0.5093 and R1/h=0.8289R_1/h=0.8289 at N=4096N=4096), the error of the solution is controlled through “the face error divided by a denominator that depends on 2ν/h2\nu/h” and cHc_H, and for N≤256N\le256 the observed orders of consecutive doublings lie only between 1.15 and 1.52, approaching 2 only for N≳1000N\gtrsim1000. For unlimited linear, on the node mesh the errors of all NN faces are O(h2)O(h^2), the residual densities of all rows tend to zero, and the error of the solution is second order from the coarse meshes on: the observed orders of consecutive doublings, from N=8→16N=8\to16 on, lie between 1.83 and 2.36 (1.98 for N=2048→4096N=2048\to4096). On the same mesh, for unlimited linear, the ∥𝐔−𝐮∗∥∞\|\mathbf U-\mathbf u^*\|_\infty of the node scheme is much smaller than the ∥𝐔−⟨u∗⟩∥∞\|\mathbf U-\langle u^*\rangle\|_\infty of the cell scheme: 2.78e−2 against 9.21e−2 at N=8N=8 (3.3 times), 3.95e−4 against 8e−3 at N=64N=64 (20.2 times) and 7.31e−8 against 6.59e−6 at N=4096N=4096 (90 times). This holds for unlimited linear only: at first order the node scheme has the larger error at every NN (2.72e−1 against 1.93e−1 at N=8N=8, 6.15e−4 against 6.13e−4 at N=4096N=4096), and with the smooth limiter the advantage (3.2 times at N=8N=8) has shrunk to 1.02 times at N=1024N=1024. (The unknowns differ, cell averages against point values; each scheme is compared with its own exact reference, so the comparison is between the two discretisation errors.)

图 22 · 格点格式与格心格式(无限制器线性,默认设计)。左:解的误差随 N;虚线是 h^2 的参考斜率;格点格式从粗网格起就是二阶,格心格式要到 N ≳ 1000 才接近二阶。右:端行的截断密度:格心的 |R_0|/h 与 |R_1|/h 趋于常数(橙、灰),格点的 |R_1|/h 与 |R_(N-1)|/h 按 h 趋于零(紫、蓝)。10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​1101001000N‖U − u*‖∞h²解的误差(无限制器线性)格点格式格心格式10-5​10-4​10-3​10-2​10-1​1101001000N端行的截断密度 |R|/hh端行(无限制器线性)格点:|R1​|/h格点:|RN−1​|/h格心:|R0​|/h格心:|R1​|/h
图 22 · 格点格式与格心格式(无限制器线性,默认设计)。左:解的误差随 NN;虚线是 h2h^2 的参考斜率;格点格式从粗网格起就是二阶,格心格式要到 N≳1000N\gtrsim1000 才接近二阶。右:端行的截断密度:格心的 ∣R0∣/h|R_0|/h 与 ∣R1∣/h|R_1|/h 趋于常数(橙、灰),格点的 ∣R1∣/h|R_1|/h 与 ∣RN−1∣/h|R_{N-1}|/h 按 hh 趋于零(紫、蓝)。
Figure 22 · The node scheme and the cell scheme (unlimited linear, default design). Left: the error of the solution against N; the dashed line is the reference slope h^2; the node scheme is second order from coarse meshes on, the cell scheme approaches second order only for N ≳ 1000. Right: the truncation density of the end rows: for the cell scheme |R_0|/h and |R_1|/h tend to constants (orange, grey), for the node scheme |R_1|/h and |R_(N-1)|/h tend to zero like h (violet, blue).10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​1101001000N‖U − u*‖∞h²error of the solution (unlimited linear)node schemecell scheme10-5​10-4​10-3​10-2​10-1​1101001000Nend-row truncation density |R|/hhend rows (unlimited linear)node: |R1​|/hnode: |RN−1​|/hcell: |R0​|/hcell: |R1​|/h
Figure 22 · The node scheme and the cell scheme (unlimited linear, default design). Left: the error of the solution against NN; the dashed line is the reference slope h2h^2; the node scheme is second order from coarse meshes on, the cell scheme approaches second order only for N≳1000N\gtrsim1000. Right: the truncation density of the end rows: for the cell scheme ∣R0∣/h|R_0|/h and ∣R1∣/h|R_1|/h tend to constants (orange, grey), for the node scheme ∣R1∣/h|R_1|/h and ∣RN−1∣/h|R_{N-1}|/h tend to zero like hh (violet, blue).

独立 Python 程序的实测。独立的稀疏程序 python/solve_node.py 在 N=32N=32 到 16384 上量过同一个残差(精确节点值代入,第 1,N−11,N-1 行与第 2,…,N−22,\dots,N-2 行的最大值),结论相同:下表取其中几个 NN。无限制器线性:边界相邻行 O(h2)O(h^2),内部行 O(h3)O(h^3);一阶:所有行 O(h2)O(h^2)(残差密度 Rj/hR_j/h 是 O(h)O(h));光滑限制器(ϵ=0.01\epsilon=0.01 固定):内部行 O(h2)O(h^2),但紧邻边界的行只是 O(h)O(h),而且 N≤256N\le256 时还不缩小。

Measured by the independent Python program. The independent sparse program python/solve_node.py measured the same residual at N=32N=32 to 16384 (exact nodal values put in; the maximum over rows 1,N−11,N-1 and over rows 2,…,N−22,\dots,N-2) and finds the same: the table takes a few NN. Unlimited linear: rows next to the boundary O(h2)O(h^2), interior rows O(h3)O(h^3); first order: every row O(h2)O(h^2) (the residual density Rj/hR_j/h is O(h)O(h)); smooth limiter (ϵ=0.01\epsilon=0.01 fixed): interior rows O(h2)O(h^2), but the rows next to the boundary only O(h)O(h), and for N≤256N\le256 they do not shrink yet.

重构,行reconstruction, rowsN=32N=32N=256N=256N=2048N=2048N=16384N=16384
一阶:行 1 与 N−1first order: rows 1 and N−14.64e−35.42e−58.07e−71.25e−8
一阶:行 2 … N−2first order: rows 2 … N−27.67e−31.20e−41.88e−62.94e−8
无限制器线性:行 1 与 N−1unlimited linear: rows 1 and N−11.05e−31.84e−52.92e−74.56e−9
无限制器线性:行 2 … N−2unlimited linear: rows 2 … N−22.28e−43.98e−77.75e−101.5e−12(此网格上受舍入限制)1.5e−12 (rounding-limited at this size)
光滑限制器:行 1 与 N−1smooth limiter: rows 1 and N−12.00e−32.36e−34.03e−45.06e−5
光滑限制器:行 2 … N−2smooth limiter: rows 2 … N−25.39e−31.20e−41.88e−62.94e−8

最后一次加密(N=2048→4096N=2048\to4096)的观测阶:无限制器线性 2.00(边界相邻行)与 3.00(内部行),一阶 2.01 与 2.00,光滑限制器 1.00 与 2.00。光滑限制器的边界相邻行在 N=32,64,128,256,512N=32,64,128,256,512 上是 2.0e−3、2.0e−3、2.6e−3、2.4e−3、1.5e−3:先不下降,N≥512N\ge512 才开始按 hh 下降。N=16384N=16384 时无限制器线性内部行的存储值 1.58e−12 受舍入限制(黏性差商是节点值之差除以 hh),表中给出的 1.5e−12 是从 N=4096N=4096 起按 h3h^3 律延续的值,独立的 50 位精度计算与它一致(到印出的位数)。与本页自己的计算比较:两者在 N=32N=32 到 4096 上的相对差别不超过 10−1510^{-15}(到所有印出的位数都相同)。

Observed orders over the last doubling (N=2048→4096N=2048\to4096): unlimited linear 2.00 (rows next to the boundary) and 3.00 (interior rows), first order 2.01 and 2.00, smooth limiter 1.00 and 2.00. The rows next to the boundary of the smooth limiter are 2.0e−3, 2.0e−3, 2.6e−3, 2.4e−3, 1.5e−3 at N=32,64,128,256,512N=32,64,128,256,512: first they do not fall, and only from N≥512N\ge512 do they fall like hh. At N=16384N=16384 the stored value of the interior rows of unlimited linear, 1.58e−12, is limited by rounding (the viscous quotient divides differences of nodal values by hh); the table gives 1.5e−12, the h3h^3 law continued from N=4096N=4096, which an independent evaluation with 50 digits confirms to the digits printed. Against this page's own computation: the relative difference is at most 10−1510^{-15} for N=32N=32 to 4096 (the two agree in every printed digit).

两处容易误读。第一,紧邻边界的两行 R1,RN−1R_1,R_{N-1} 比内部行低一阶,并不说明边界拖累了精度:解的误差由面误差通过有界的 KNK_N 控制,而不是由行的截断误差控制;R1R_1 是一行 O(h2)O(h^2) 的误差,N−3N-3 个内部行各是 O(h3)O(h^3),它们对解的误差贡献同一个量级 h2h^2。第二,粗网格上的观测阶还不是渐近阶:N=8N=8 时 K8=3.43K_8=3.43 比极限 2.502.50 大,N≤32N\le32 的数字不要当作格式的阶(第 15 节系统地测量阶)。

Two things are easily misread. First, that the two rows next to the boundary, R1R_1 and RN−1R_{N-1}, are one order less accurate than the interior rows does not mean the boundary drags the accuracy down: the error of the solution is controlled by the face errors through the bounded KNK_N, not by the truncation errors of the rows; R1R_1 is one row with an error O(h2)O(h^2), the N−3N-3 interior rows are each O(h3)O(h^3), and they contribute the same order h2h^2 to the error of the solution. Second, the observed orders on coarse meshes are not yet asymptotic: K8=3.43K_8=3.43 at N=8N=8 is above its limit 2.502.50, and the numbers for N≤32N\le32 should not be taken for the order of the scheme (Section 15 measures the orders systematically).

用加密播放器一步步看:每一步 NN 加倍,左图是截断误差的分布 ∣Rj(𝐮∗)∣/h|R_j(\mathbf u^*)|/h,中图是面误差 ζf\zeta_f,右图是解的误差 Uj−u∗(xj)U_j-u^*(x_j)。

Step through it with the refinement player: each step doubles NN; the left panel is the distribution of the truncation error ∣Rj(𝐮∗)∣/h|R_j(\mathbf u^*)|/h, the middle panel the face errors ζf\zeta_f, the right panel the error of the solution Uj−u∗(xj)U_j-u^*(x_j).

第 5 节Section 5

残差与 Newton 求解

The residual and the Newton solve

本节实验:第 4 节说,精确节点值上各面的通量误差 ζf\zeta_f 并不相等。那么解满足 R(𝐔,D)=0R(\mathbf U,D)=0 时,各个面通量 Hf(𝐔)H_f(\mathbf U) 满足什么?先预测,再看图 23。第二问:N=8N=8 时 Newton 法要迭代几次?残差是二次收敛的吗?

Experiment: Section 4 says that the face errors ζf\zeta_f at the exact nodal values are not equal. What, then, do the face fluxes Hf(𝐔)H_f(\mathbf U) satisfy once R(𝐔,D)=0R(\mathbf U,D)=0 holds? Predict, then look at Figure 23. Second question: how many Newton iterations does N=8N=8 need, and does the residual fall quadratically?

第 3、4 节给出了每个面的通量和两个约束行。本节把它们装配成残差(它的零点就是离散解),说明“解出来了”是什么意思,再用 Newton 法解 R=0R=0。

Sections 3 and 4 gave the flux of every face and the two constraint rows. This section assembles them into the residual, the function whose zero is the discrete solution, says what “solved” means, and solves R=0R=0 by Newton's method.

残差代码

The residual code

残差由一个面循环算出:每个面只访问一次,通量只算一次,然后分发给面两侧的两个节点(左节点加、右节点减),最后用两个约束行覆盖边界节点的行。下表是本页 model.js 中 residual 的语句,标号 0、1a、1b、1c、2、3、4a、4b、5 与第 8、9 节的前向代码和反向代码一致(反向代码以相反的次序执行同样的语句,标号加撇:5′,4b′,…,1a′5',4\mathrm b',\dots,1\mathrm a'):

The residual is computed by one loop over the faces: each face is visited once, its flux is computed once and scattered to the two nodes on its two sides (plus to the left node, minus to the right node), and finally the two constraint rows overwrite the rows of the boundary nodes. The table lists the statements of residual in this page's model.js; the labels 0, 1a, 1b, 1c, 2, 3, 4a, 4b, 5 are those of the forward and reverse codes of Sections 8 and 9 (the reverse code runs the same statements in the opposite order, with a prime on the label: 5′,4b′,…,1a′5',4\mathrm b',\dots,1\mathrm a'):

#语句Statement它是什么What it is
0R←0R\leftarrow0装配之前把残差置零the zeroing before the assembly
1alj=Uj−Uj−1,  rj=Uj+1−Uj  (1≤j≤N−1)l_j=U_j-U_{j-1},\ \ r_j=U_{j+1}-U_j\ \ (1\le j\le N-1)内部节点上的两个单侧差分the two one-sided differences at the interior nodes
1bσj=σ(lj,rj)  (1≤j≤N−1)\sigma_j=\sigma(l_j,r_j)\ \ (1\le j\le N-1);σ0=U1−U0\sigma_0=U_1-U_0,σN=UN−UN−1\sigma_N=U_N-U_{N-1}(一阶:σ0=σN=0\sigma_0=\sigma_N=0)σj=σ(lj,rj)  (1≤j≤N−1)\sigma_j=\sigma(l_j,r_j)\ \ (1\le j\le N-1); σ0=U1−U0\sigma_0=U_1-U_0, σN=UN−UN−1\sigma_N=U_N-U_{N-1} (first order: σ0=σN=0\sigma_0=\sigma_N=0)第 3 节的斜率;两个端点节点用单侧差分the slopes of Section 3; the two end nodes use one-sided differences
1cqL=Uf+12σf, UL=Uf;  qR=Uf+1−12σf+1, UR=Uf+1  (0≤f≤N−1)q_L=U_f+\tfrac12\sigma_f,\ U_L=U_f;\ \ q_R=U_{f+1}-\tfrac12\sigma_{f+1},\ U_R=U_{f+1}\ \ (0\le f\le N-1)面 ff 的两个迹(重构)和两个未重构状态the two traces (reconstructed) and the two raw states of face ff
2Hf=14(qL2+qR2)−(qR−qL)−ν UR−ULdfH_f=\tfrac14(q_L^2+q_R^2)-(q_R-q_L)-\nu\,\frac{U_R-U_L}{d_f},df=hd_f=hHf=14(qL2+qR2)−(qR−qL)−ν UR−ULdfH_f=\tfrac14(q_L^2+q_R^2)-(q_R-q_L)-\nu\,\frac{U_R-U_L}{d_f}, df=hd_f=h第 3 节的面通量the face flux of Section 3
3Rf+=Hf (f≥1);  Rf+1-=Hf (f≤N−2)R_f\mathrel{\text{+=}}H_f\ (f\ge1);\ \ R_{f+1}\mathrel{\text{-=}}H_f\ (f\le N-2)分发:加到左边的节点、从右边的节点减去;两个边界面各只作用于一个内部节点the scatter: plus to the left node, minus to the right node; each of the two boundary faces acts on one interior node only
4aQf=q∗(xf+1/2;D)  (0≤f≤N−1)Q_f=q^*(x_{f+1/2};D)\ \ (0\le f\le N-1)各个面上的精确通量the exact flux of every face
4bRj-=Qj−Qj−1  (1≤j≤N−1)R_j\mathrel{\text{-=}}Q_j-Q_{j-1}\ \ (1\le j\le N-1)精确的积分源项(下面)the exact integrated source (below)
5uin=u∗(0;D), uout=u∗(1;D);  R0=U0−uin, RN=UN−uoutu_{\rm in}=u^*(0;D),\ u_{\rm out}=u^*(1;D);\ \ R_0=U_0-u_{\rm in},\ R_N=U_N-u_{\rm out}第 4 节的约束行,覆盖两个边界行the constraint rows of Section 4, overwriting the two boundary rows
residual(U, D) -> res                    U = (U[0], ..., U[N]), D = (a, phi, nu)
 0    res = 0;  s = 0                          (一阶:s[0] = s[N] = 0 保持不变)
      for j = 1 .. N-1:
 1a     l = U[j] - U[j-1];  r = U[j+1] - U[j]
 1b     s[j] = sigma(l, r)                     第 3 节的 sigma_j(不是源项 s(x))
 1b   s[0] = U[1] - U[0];  s[N] = U[N] - U[N-1]   二阶:端点的单侧斜率
      for f = 0 .. N-1:
 1c     qL = U[f] + s[f]/2;      UL = U[f]
        qR = U[f+1] - s[f+1]/2;  UR = U[f+1]
 2      d = h;  H = (qL^2 + qR^2)/4 - (qR - qL) - nu*(UR - UL)/d
 3      if f >= 1:   res[f]   += H
        if f <= N-2: res[f+1] -= H
      for f = 0 .. N-1:
 4a     Q[f] = q*(x_{f+1/2}; D)
      for j = 1 .. N-1:
 4b     res[j] -= Q[j] - Q[j-1]
 5    uin = u*(0; D);  uout = u*(1; D)
      res[0] = U[0] - uin;  res[N] = U[N] - uout
      return res
residual(U, D) -> res                    U = (U[0], ..., U[N]), D = (a, phi, nu)
 0    res = 0;  s = 0                          (s[0] = s[N] = 0 stay at first order)
      for j = 1 .. N-1:
 1a     l = U[j] - U[j-1];  r = U[j+1] - U[j]
 1b     s[j] = sigma(l, r)                     sigma_j of Section 3 (not the source s(x))
 1b   s[0] = U[1] - U[0];  s[N] = U[N] - U[N-1]   second order: one-sided end slopes
      for f = 0 .. N-1:
 1c     qL = U[f] + s[f]/2;      UL = U[f]
        qR = U[f+1] - s[f+1]/2;  UR = U[f+1]
 2      d = h;  H = (qL^2 + qR^2)/4 - (qR - qL) - nu*(UR - UL)/d
 3      if f >= 1:   res[f]   += H
        if f <= N-2: res[f+1] -= H
      for f = 0 .. N-1:
 4a     Q[f] = q*(x_{f+1/2}; D)
      for j = 1 .. N-1:
 4b     res[j] -= Q[j] - Q[j-1]
 5    uin = u*(0; D);  uout = u*(1; D)
      res[0] = U[0] - uin;  res[N] = U[N] - uout
      return res

语句 1c 里的面数据(qL,qR,UL,URq_L,q_R,U_L,U_R)就是第 3 节的取值与重构,语句 2 是第 3 节的通量(所有面的 df=hd_f=h),语句 3 的两个 if 让两个边界面各只作用于一个内部节点(面 00 只从 R1R_1 减去,面 N−1N-1 只加到 RN−1R_{N-1}),语句 4a、4b 是下面的精确源项,语句 5 是第 4 节的约束行。model.js 在一个节点循环里算斜率(1a、1b),在一个面循环里算出所有面的数组(1c、2),用第二个面循环按同样的顺序分发(3),再逐节点减去源项(4a、4b),最后写两个约束行(5);浮点运算的次序完全相同,所以下面的播放器按这段伪代码重放,得到的 RR 与 model.js 逐位相同(已验证)。

The face data of statement 1c (qL,qR,UL,URq_L,q_R,U_L,U_R) are the gathering and reconstruction of Section 3, statement 2 is the flux of Section 3 (df=hd_f=h for every face), the two ifs of statement 3 make each boundary face act on one interior node only (face 00 only subtracts from R1R_1, face N−1N-1 only adds to RN−1R_{N-1}), statements 4a and 4b are the exact source below, and statement 5 is the constraint rows of Section 4. model.js computes the slopes in a node loop (1a, 1b), the arrays of all faces in a face loop (1c, 2), scatters them in a second face loop in the same order (3), subtracts the source node by node (4a, 4b) and writes the two constraint rows last (5); the floating-point operations happen in the same sequence, so the player below, which replays this pseudocode, gets the same RR as model.js bit for bit (verified).

精确的积分源项

The exact integrated source

节点 jj 的残差是 qx−sq_x-s 在它的对偶控制体 Vj=[xj−h2, xj+h2]V_j=[x_j-\tfrac h2,\,x_j+\tfrac h2] 上的积分。通量部分给出 Hj−Hj−1H_j-H_{j-1}(面 jj 在它的右边,面 j−1j-1 在它的左边);源项部分,因为构造时就令 s=qx∗s=q^*_x(第 1 节),由微积分基本定理得

The residual of node jj is the integral of qx−sq_x-s over its dual volume Vj=[xj−h2, xj+h2]V_j=[x_j-\tfrac h2,\,x_j+\tfrac h2]. The flux part gives Hj−Hj−1H_j-H_{j-1} (face jj is its right boundary, face j−1j-1 its left boundary); for the source part, since s=qx∗s=q^*_x by construction (Section 1), the fundamental theorem of calculus gives

Sj=∫xj−h/2xj+h/2s dx=Qj−Qj−1,Rj(𝐔,D)=Hj−Hj−1−(Qj−Qj−1)(1≤j≤N−1).S_j=\int_{x_j-h/2}^{x_j+h/2}s\,\mathrm dx=Q_j-Q_{j-1},\qquad R_j(\mathbf U,D)=H_j-H_{j-1}-(Q_j-Q_{j-1})\quad(1\le j\le N-1).

这里不需要求积公式,对任何 NN 都精确;两个边界节点的行是约束,不带源项。验算:在每个对偶控制体上用 20 点 Gauss 求积积分 s=u∗ux∗−νuxx∗s=u^*u^*_x-\nu u^*_{xx},与 Qj−Qj−1Q_j-Q_{j-1} 的最大差不超过 2×10−152\times10^{-15}(N=8N=8)。所以残差唯一的误差来源是数值通量,第 4 节才能写出 Rj(𝐮∗)=ζj−ζj−1R_j(\mathbf u^*)=\zeta_j-\zeta_{j-1}。

No quadrature rule is needed, and the source is exact for every NN; the rows of the two boundary nodes are constraints and carry no source. Check: integrating s=u∗ux∗−νuxx∗s=u^*u^*_x-\nu u^*_{xx} over every dual volume with 20 Gauss points gives Qj−Qj−1Q_j-Q_{j-1} to within 2×10−152\times10^{-15} (N=8N=8). The numerical flux is therefore the only source of error in the residual, which is why Section 4 could write Rj(𝐮∗)=ζj−ζj−1R_j(\mathbf u^*)=\zeta_j-\zeta_{j-1}.

守恒:把第 1,…,N−11,\dots,N-1 行加起来,内部面的通量成对抵消,只剩两个边界面:

Conservation: adding rows 1,…,N−11,\dots,N-1, the fluxes of the interior faces cancel in pairs and only the two boundary faces remain:

∑j=1N−1Rj=(HN−1−QN−1)−(H0−Q0).\sum_{j=1}^{N-1}R_j=(H_{N-1}-Q_{N-1})-(H_0-Q_0).

这是并集 V1∪⋯∪VN−1=[h2, 1−h2]V_1\cup\dots\cup V_{N-1}=[\tfrac h2,\,1-\tfrac h2] 的通量平衡,穿过它两端的就是面 00 和面 N−1N-1(两个约束行不参与)。在 Newton 初值(精确节点值,N=8N=8)处,无限制器线性:等式两边都是 −0.025441574669;一阶是 0.057130192519,光滑限制器是 −0.062373925744(两边相同)。

This is the flux balance of the union V1∪⋯∪VN−1=[h2, 1−h2]V_1\cup\dots\cup V_{N-1}=[\tfrac h2,\,1-\tfrac h2]: what crosses its two ends is face 00 and face N−1N-1 (the two constraint rows do not take part). At the Newton initial guess (the exact nodal values, N=8N=8), unlimited linear: both sides are −0.025441574669; first order gives 0.057130192519 and the smooth limiter −0.062373925744 (the two sides agree).

“解出来了”是什么意思:R=0R=0 等价于各面通量误差相等

What “solved” means: R=0R=0 makes the flux error one constant

第 1,…,N−11,\dots,N-1 行全为零,就是 Hj−Qj=Hj−1−Qj−1H_j-Q_j=H_{j-1}-Q_{j-1} 对 j=1,…,N−1j=1,\dots,N-1 都成立:全部 NN 个面上的通量误差都相同。

Rows 1,…,N−11,\dots,N-1 all vanishing says Hj−Qj=Hj−1−Qj−1H_j-Q_j=H_{j-1}-Q_{j-1} for j=1,…,N−1j=1,\dots,N-1: the flux mismatch is the same on all NN faces.

R1=⋯=RN−1=0  ⟺  Hf(𝐔)=Qf+cH(f=0,…,N−1).R_1=\dots=R_{N-1}=0\iff H_f(\mathbf U)=Q_f+c_H\quad(f=0,\dots,N-1).

这里 cHc_H 是同一个常数(下标 HH 表示通量,它与第 3 节的偏导 cL,cRc_L,c_R 无关)。连续解的通量就是 q∗q^*(第 4 节开头);离散解的通量是精确通量加一个常数 cHc_H:N−1N-1 个方程定下 N−1N-1 个内部未知量,剩下的这个常数就是边界留下的痕迹(两个约束行不在其中:它们只定下 U0,UNU_0,U_N)。格心页是 N+1N+1 个面、NN 个方程,这里是 NN 个面、N−1N-1 个方程。默认设计(N=8N=8,取各面平均):无限制器线性的 cHc_H 是 −0.004807,一阶是 −0.123543,光滑限制器是 0.000308,各面与它之差不超过 2×10−142\times10^{-14}。加密后 cH→0c_H\to0:N=4096N=4096 时无限制器线性是 −1.72e−8,一阶是 −2.85e−4(第 4 节列出了无限制器线性的 cHc_H 的两次变号:它不单调)。

Here cHc_H is one and the same constant (the subscript HH stands for the flux; it has nothing to do with the partial derivatives cL,cRc_L,c_R of Section 3). The continuous solution has the flux q∗q^* (beginning of Section 4); the discrete solution has the exact flux plus a constant cHc_H: N−1N-1 equations fix the N−1N-1 interior unknowns, and the constant that is left over is what the boundary leaves behind (the two constraint rows are not among them: they only fix U0U_0 and UNU_N). The cell-centred page has N+1N+1 faces and NN equations, here there are NN faces and N−1N-1 equations. At the defaults (N=8N=8, the mean over the faces) cHc_H is −0.004807 for unlimited linear, −0.123543 for first order and 0.000308 for the smooth limiter, every face within 2×10−142\times10^{-14} of it. Under refinement cH→0c_H\to0: −1.72e−8 at N=4096N=4096 for unlimited linear, −2.85e−4 for first order (Section 4 lists the two sign changes of cHc_H of unlimited linear: it is not monotone).

图 23 · 逐面装配(默认设计,N=8,无限制器线性)。上:数值通量 H_f(柱)与精确通量 Q_f(圆圈);中:它们的差 H_f-Q_f;下:残差 R_j=(H_j-Q_j)-(H_(j-1)-Q_(j-1)),画在节点上,第 0 行与第 N 行是约束行。左:Newton 初值,也就是精确节点值,面失配就是第 4 节的面误差 ζ_f,各面不同,所以 R_j(相邻两个面失配之差)不为零,两个约束行为零;右:收敛解,每个面的失配都等于同一个 c_H(虚线),所以 R_j=0。两列用同一个纵轴刻度。00.20.40.60.800.20.40.60.81面 xf+1/2​Hf​Newton 初值(精确节点值)数值通量 Hf​精确通量 Qf​−0.03−0.02−0.0100.010.020.0300.20.40.60.81面 xf+1/2​Hf​ − Qf​−0.03−0.02−0.0100.010.020.0300.20.40.60.81节点 xj​(行 0 与行 N 是约束行)Rj​00.20.40.60.800.20.40.60.81面 xf+1/2​Hf​收敛解数值通量 Hf​精确通量 Qf​−0.03−0.02−0.0100.010.020.0300.20.40.60.81面 xf+1/2​Hf​ − Qf​cH​ = −0.0048−0.03−0.02−0.0100.010.020.0300.20.40.60.81节点 xj​(行 0 与行 N 是约束行)Rj​
图 23 · 逐面装配(默认设计,N=8N=8,无限制器线性)。上:数值通量 HfH_f(柱)与精确通量 QfQ_f(圆圈);中:它们的差 Hf−QfH_f-Q_f;下:残差 Rj=(Hj−Qj)−(Hj−1−Qj−1)R_j=(H_j-Q_j)-(H_{j-1}-Q_{j-1}),画在节点上,第 00 行与第 NN 行是约束行。左:Newton 初值,也就是精确节点值,面失配就是第 4 节的面误差 ζf\zeta_f,各面不同,所以 RjR_j(相邻两个面失配之差)不为零,两个约束行为零;右:收敛解,每个面的失配都等于同一个 cHc_H(虚线),所以 Rj=0R_j=0。两列用同一个纵轴刻度。
Figure 23 · Assembly face by face (default design, N=8, unlimited linear). Top: the numerical flux H_f (bars) and the exact flux Q_f (rings); middle: their difference H_f-Q_f; bottom: the residual R_j=(H_j-Q_j)-(H_(j-1)-Q_(j-1)), drawn at the nodes, rows 0 and N being the constraint rows. Left: the Newton initial guess, which is the vector of exact nodal values, so the face mismatch is the face error ζ_f of Section 4; the faces differ and R_j, the difference of two neighbouring face mismatches, is not zero (the two constraint rows are). Right: the converged solution; every face has the same mismatch c_H (dashed), so R_j=0. Both columns share the vertical scale.00.20.40.60.800.20.40.60.81face xf+1/2​Hf​Newton initial guess (exact nodal values)numerical flux Hf​exact flux Qf​−0.03−0.02−0.0100.010.020.0300.20.40.60.81face xf+1/2​Hf​ − Qf​−0.03−0.02−0.0100.010.020.0300.20.40.60.81node xj​ (rows 0 and N are the constraint rows)Rj​00.20.40.60.800.20.40.60.81face xf+1/2​Hf​converged solutionnumerical flux Hf​exact flux Qf​−0.03−0.02−0.0100.010.020.0300.20.40.60.81face xf+1/2​Hf​ − Qf​cH​ = −0.0048−0.03−0.02−0.0100.010.020.0300.20.40.60.81node xj​ (rows 0 and N are the constraint rows)Rj​
Figure 23 · Assembly face by face (default design, N=8N=8, unlimited linear). Top: the numerical flux HfH_f (bars) and the exact flux QfQ_f (rings); middle: their difference Hf−QfH_f-Q_f; bottom: the residual Rj=(Hj−Qj)−(Hj−1−Qj−1)R_j=(H_j-Q_j)-(H_{j-1}-Q_{j-1}), drawn at the nodes, rows 00 and NN being the constraint rows. Left: the Newton initial guess, which is the vector of exact nodal values, so the face mismatch is the face error ζf\zeta_f of Section 4; the faces differ and RjR_j, the difference of two neighbouring face mismatches, is not zero (the two constraint rows are). Right: the converged solution; every face has the same mismatch cHc_H (dashed), so Rj=0R_j=0. Both columns share the vertical scale.

实际中“解出来了”指 Newton 修正 ∥Δ𝐔∥∞≤10−13\|\Delta\mathbf U\|_\infty\le10^{-13}(或 ∥R∥∞<10−15\|R\|_\infty<10^{-15})。残差本身降不到舍入误差的底线以下:每个 RjR_j 是两个约 0.50.5 的通量之差,舍入误差约 10−1610^{-16} 到 10−1510^{-15}。

In practice “solved” means a Newton correction ∥Δ𝐔∥∞≤10−13\|\Delta\mathbf U\|_\infty\le10^{-13} (or ∥R∥∞<10−15\|R\|_\infty<10^{-15}). The residual itself cannot fall below its rounding floor: each RjR_j is a difference of fluxes of about 0.50.5, with rounding errors of about 10−1610^{-16} to 10−1510^{-15}.

下面的播放器一次执行一条语句:选择 Newton 初值、收敛解或精确节点值,看每个面的取值、通量和分发怎样一步步把 RR 堆起来。

The player below executes the pseudocode one statement at a time: choose the Newton initial guess, the converged solution or the exact nodal values, and watch the gather, the flux and the scatter of each face build up RR step by step.

Newton 法,就是 model.solve 的做法

Newton's method as model.solve does it

线性化(A=R𝐔A=R_{\mathbf U},第 6 节):

Linearise (A=R𝐔A=R_{\mathbf U}, Section 6):

R(𝐔+Δ𝐔)=R(𝐔)+A(𝐔) Δ𝐔+O(∥Δ𝐔∥2).R(\mathbf U+\Delta\mathbf U)=R(\mathbf U)+A(\mathbf U)\,\Delta\mathbf U+O(\|\Delta\mathbf U\|^2).

令线性近似 R(𝐔)+A Δ𝐔R(\mathbf U)+A\,\Delta\mathbf U 为零,得到 Newton 修正 A(𝐔k) Δ𝐔k=−R(𝐔k)A(\mathbf U^k)\,\Delta\mathbf U^k=-R(\mathbf U^k)。本页的求解器 solve 逐条语句如下:

Setting the linear approximation R(𝐔)+A Δ𝐔R(\mathbf U)+A\,\Delta\mathbf U to zero gives the Newton correction A(𝐔k) Δ𝐔k=−R(𝐔k)A(\mathbf U^k)\,\Delta\mathbf U^k=-R(\mathbf U^k). The page's solver solve is, statement by statement:

solve(D):
 U = (u*(x_0), ..., u*(x_N))                      精确节点值:只是初始猜测(R_0 = R_N = 0 已经成立)
 for k = 0, 1, ..., 34:
   R = residual(U, D);  A = R_U(U, D)               (N+1 次前向求值,第 6 节)
   解 A dU = -R                                     (LU;dU[0] = dU[N] = 0:约束行已经满足)
   记录 ||R||_inf, ||dU||_inf
   if ||dU||_inf <= 1e-13 or ||R||_inf < 1e-15:  return U   已收敛(dU 不再加上)
   t = 1
   至多 25 次:
     Ut = U + t dU
     if 0.1 < min Ut, max Ut < 1.9 and ||R(Ut, D)||_inf < (1 - 1e-4 t) ||R||_inf:
       U = Ut;  转到下一个 k
     t = t/2
   return U   线搜索失败
 return U   达到迭代上限
solve(D):
 U = (u*(x_0), ..., u*(x_N))                      exact nodal values: an initial guess only (R_0 = R_N = 0 already)
 for k = 0, 1, ..., 34:
   R = residual(U, D);  A = R_U(U, D)               (N+1 forward evaluations, Section 6)
   solve A dU = -R                                  (LU; dU[0] = dU[N] = 0: the constraint rows are satisfied)
   record ||R||_inf, ||dU||_inf
   if ||dU||_inf <= 1e-13 or ||R||_inf < 1e-15:  return U   converged (dU is not added)
   t = 1
   at most 25 times:
     Ut = U + t dU
     if 0.1 < min Ut, max Ut < 1.9 and ||R(Ut, D)||_inf < (1 - 1e-4 t) ||R||_inf:
       U = Ut;  go on with the next k
     t = t/2
   return U   line search failed
 return U   iteration limit

几点说明。初始猜测是精确节点值(页面知道精确解,但只把它当作起点;结果是离散解,不是 u∗u^*)。约束行是线性的,初始猜测又在两端精确,所以每个迭代值都有 R0=RN=0R_0=R_N=0,每步修正在两个边界节点上为零:Newton 法实际只改变内部节点,用的是第 6 节的内部块 AIIA_{\rm II}。先试整步,回溯把步长 tt 减半(这里 tt 是步长;第 8、10、11 节用 tt 表示别的参数),直到试探状态在 0.1<U<1.90.1<U<1.9 之内而且残差降到旧值的 (1−10−4t)(1-10^{-4}t) 倍以下;修正量 ≤10−13\le10^{-13} 时停止,返回最后一个迭代值(最后一次修正不加上)。默认设计下三种重构的每一步都是整步 t=1t=1(已验证;按同一算法重放线搜索,得到的每个迭代值逐位相同)。N=8N=8 时需要的迭代次数(计入最后那次只检查、不更新的迭代):一阶 5,无限制器线性 4,光滑限制器 6。

Some details. The initial guess is the vector of exact nodal values (the page knows the exact solution but uses it only as a starting point; the result is the discrete solution, not u∗u^*). The constraint rows are linear and the initial guess is exact at both ends, so every iterate has R0=RN=0R_0=R_N=0 and every correction vanishes at the two boundary nodes: Newton's method really changes the interior nodes only, with the interior block AIIA_{\rm II} of Section 6. The full step is tried first and the backtracking halves the step length tt (here tt is the step length; Sections 8, 10 and 11 use tt for other parameters) until the trial state stays inside 0.1<U<1.90.1<U<1.9 and the residual falls below (1−10−4t)(1-10^{-4}t) times its old value; the iteration stops when the correction is ≤10−13\le10^{-13} and returns the last iterate (the last correction is not added). At the defaults every step of all three reconstructions is a full step t=1t=1 (verified; replaying the line search of the same algorithm reproduces every iterate bit for bit). The number of iterations at N=8N=8 (counting the last one, which only checks and does not update): 5 for first order, 4 for unlimited linear and 6 for the smooth limiter.

二次收敛,精确地写出来

Quadratic convergence, written out exactly

一阶与无限制器线性重构时,残差是 𝐔\mathbf U 的二次多项式:HH 对迹是二次的,迹对 𝐔\mathbf U 是线性的,两个约束行是线性的。所以 Taylor 展开止于二次项,整步之后的残差恰好就是二次余项:

For first-order and unlimited linear reconstruction the residual is a quadratic polynomial in 𝐔\mathbf U: HH is quadratic in the traces, the traces are linear in 𝐔\mathbf U and the two constraint rows are linear. The Taylor expansion therefore stops at the quadratic term, and after a full step the residual is exactly the quadratic remainder:

Rj(𝐔k+Δ𝐔k)=χj−χj−1  (1≤j≤N−1),R0=RN=0,χf=14[(ΔqL)f2+(ΔqR)f2]≥0,R_j(\mathbf U^k+\Delta\mathbf U^k)=\chi_j-\chi_{j-1}\ \ (1\le j\le N-1),\quad R_0=R_N=0,\qquad\chi_f=\tfrac14\bigl[(\Delta q_L)_f^2+(\Delta q_R)_f^2\bigr]\ge0,

其中 ΔqL,ΔqR\Delta q_L,\Delta q_R 是 Δ𝐔k\Delta\mathbf U^k 的迹增量,f=0,…,N−1f=0,\dots,N-1。于是 ∥R(𝐔k+1)∥∞≤C ∥Δ𝐔k∥∞2\|R(\mathbf U^{k+1})\|_\infty\le C\,\|\Delta\mathbf U^k\|_\infty^2。无限制器线性时每个迹增量是至多三个节点增量的组合(内部面的权是 1,±141,\pm\tfrac14,边界面的权是 12,12\tfrac12,\tfrac12 与 1,±141,\pm\tfrac14),所以 ∣Δq∣≤32∥Δ𝐔∥∞|\Delta q|\le\tfrac32\|\Delta\mathbf U\|_\infty,χf≤98∥Δ𝐔∥∞2\chi_f\le\tfrac98\|\Delta\mathbf U\|_\infty^2;又因为 χf≥0\chi_f\ge0,两个非负数之差不超过其中较大者:∣Rj∣=∣χj−χj−1∣≤max⁡fχf≤98∥Δ𝐔∥∞2|R_j|=|\chi_j-\chi_{j-1}|\le\max_f\chi_f\le\tfrac98\|\Delta\mathbf U\|_\infty^2。简单的界是 C=98C=\tfrac98(两个边界面也满足)。一阶时迹就是节点值,χj\chi_j 与 χj−1\chi_{j-1} 共有的项 14ΔUj2\tfrac14\Delta U_j^2 在差里抵消,每一行(第 11 行和第 N−1N-1 行也一样)都是 Rj(𝐔k+1)=14(ΔUj+12−ΔUj−12)R_j(\mathbf U^{k+1})=\tfrac14(\Delta U_{j+1}^2-\Delta U_{j-1}^2);Newton 修正在两个边界节点上为零,所以 R1=14ΔU22R_1=\tfrac14\Delta U_2^2,RN−1=−14ΔUN−22R_{N-1}=-\tfrac14\Delta U_{N-2}^2:C=14C=\tfrac14,对一般的 Δ𝐔\Delta\mathbf U(取 Δ𝐔=e2\Delta\mathbf U=e_2)不能再小。两个边界附近的行与内部行是同一个公式,没有特殊的行。

where ΔqL,ΔqR\Delta q_L,\Delta q_R are the trace increments of Δ𝐔k\Delta\mathbf U^k, f=0,…,N−1f=0,\dots,N-1. Hence ∥R(𝐔k+1)∥∞≤C ∥Δ𝐔k∥∞2\|R(\mathbf U^{k+1})\|_\infty\le C\,\|\Delta\mathbf U^k\|_\infty^2. For unlimited linear every trace increment is a combination of at most three nodal increments (weights 1,±141,\pm\tfrac14 at an interior face, 12,12\tfrac12,\tfrac12 and 1,±141,\pm\tfrac14 at the boundary faces), so ∣Δq∣≤32∥Δ𝐔∥∞|\Delta q|\le\tfrac32\|\Delta\mathbf U\|_\infty and χf≤98∥Δ𝐔∥∞2\chi_f\le\tfrac98\|\Delta\mathbf U\|_\infty^2; since χf≥0\chi_f\ge0, the difference of two of them is at most the larger one: ∣Rj∣=∣χj−χj−1∣≤max⁡fχf≤98∥Δ𝐔∥∞2|R_j|=|\chi_j-\chi_{j-1}|\le\max_f\chi_f\le\tfrac98\|\Delta\mathbf U\|_\infty^2. The simple bound is C=98C=\tfrac98 (the two boundary faces satisfy it too). At first order the traces are the nodal values, the term 14ΔUj2\tfrac14\Delta U_j^2 shared by χj\chi_j and χj−1\chi_{j-1} cancels in their difference, and every row, rows 11 and N−1N-1 included, is Rj(𝐔k+1)=14(ΔUj+12−ΔUj−12)R_j(\mathbf U^{k+1})=\tfrac14(\Delta U_{j+1}^2-\Delta U_{j-1}^2); a Newton correction vanishes at the two boundary nodes, so R1=14ΔU22R_1=\tfrac14\Delta U_2^2 and RN−1=−14ΔUN−22R_{N-1}=-\tfrac14\Delta U_{N-2}^2: C=14C=\tfrac14, and no smaller constant works for a general Δ𝐔\Delta\mathbf U (take Δ𝐔=e2\Delta\mathbf U=e_2). The rows next to the boundary follow the same formula as the interior rows: no row is special.

这就是二次收敛。实测:余项恒等式在第 kk 次迭代的整步上成立到 10−1410^{-14}(N=8N=8,所有迭代,一阶与无限制器线性);N=8N=8 到 128 的全部 Newton 步上 ∥Rk+1∥∞/∥Δ𝐔k∥∞2\|R^{k+1}\|_\infty/\|\Delta\mathbf U^k\|_\infty^2 的最大值是一阶 0.250、无限制器线性 0.444,都在各自的界以内;N=8N=8 时前几步的比值是一阶 0.203、0.235、0.250,无限制器线性 0.414、0.405。光滑斜率是有理函数,残差不是多项式,没有这样的恒等式;Taylor 定理仍然给出类似的界,但常数依赖斜率函数 σ\sigma 的二阶导数,本页不给出它的值。光滑限制器在 N=8N=8 需要 6 次迭代,前两步的残差只降到上一步的 0.53 倍和 0.05 倍,之后才二次收敛;上述比值的最大值是 62.99,没有一阶与无限制器线性那样小的普适常数。

This is quadratic convergence. Measured: the remainder identity holds on the full step of every iteration to within 10−1410^{-14} (N=8N=8, all iterations, first order and unlimited linear); over all Newton steps for N=8N=8 to 128 the largest ∥Rk+1∥∞/∥Δ𝐔k∥∞2\|R^{k+1}\|_\infty/\|\Delta\mathbf U^k\|_\infty^2 is 0.250 at first order and 0.444 for unlimited linear, both within their bounds; at N=8N=8 the ratios of the first steps are 0.203, 0.235, 0.250 at first order and 0.414, 0.405 for unlimited linear. The smooth slope is a rational function, the residual is no polynomial and there is no such identity; Taylor's theorem still gives a bound of this kind, but its constant depends on the second derivatives of the slope function σ\sigma and this page does not give its value. With the smooth limiter Newton's method needed 6 iterations at N=8N=8, its residual fell only to 0.53 and 0.05 times the previous value in the first two steps, and quadratically after that; the largest of the ratios above is 62.99, with no small universal constant as at first order and for unlimited linear.

图 24 · 一眼看出二次收敛:每个 Newton 步的修正 ‖ΔU^k‖_∞(横轴)对下一个残差 ‖R(U^(k+1))‖_∞(纵轴),N=8 到 128、三种重构的全部步(低于舍入误差底线的点未画)。虚线是上面证明的界 1/4‖ΔU‖^2(一阶)与 9/8‖ΔU‖^2(无限制器线性):这两种重构的点都在各自的线上或线下(最大比值 0.250 与 0.444;对数坐标里两条线的斜率都是 2)。光滑限制器的残差不是多项式,最大比值是 62.99。10-14​10-12​10-10​10-8​10-6​10-4​10-2​110-7​10-6​10-5​10-4​10-3​10-2​10-1​1Newton 修正 ‖ΔUk​‖∞下一个残差 ‖R(Uk+1​)‖∞一阶无限制器线性光滑限制器¼‖ΔU‖²(9/8)‖ΔU‖²
图 24 · 一眼看出二次收敛:每个 Newton 步的修正 ∥Δ𝐔k∥∞\|\Delta\mathbf U^k\|_\infty(横轴)对下一个残差 ∥R(𝐔k+1)∥∞\|R(\mathbf U^{k+1})\|_\infty(纵轴),N=8N=8 到 128、三种重构的全部步(低于舍入误差底线的点未画)。虚线是上面证明的界 14∥Δ𝐔∥2\tfrac14\|\Delta\mathbf U\|^2(一阶)与 98∥Δ𝐔∥2\tfrac98\|\Delta\mathbf U\|^2(无限制器线性):这两种重构的点都在各自的线上或线下(最大比值 0.250 与 0.444;对数坐标里两条线的斜率都是 2)。光滑限制器的残差不是多项式,最大比值是 62.99。
Figure 24 · Quadratic convergence at a glance: the correction ‖ΔU^k‖_∞ of every Newton step (horizontal) against the next residual ‖R(U^(k+1))‖_∞ (vertical), all steps for N=8 to 128 and the three reconstructions (points below the rounding floor left out). The dashed lines are the bounds proved above, 1/4‖ΔU‖^2 (first order) and 9/8‖ΔU‖^2 (unlimited linear): the points of these two reconstructions lie on or below their lines (largest ratios 0.250 and 0.444; on the log-log axes both lines have slope 2). The residual of the smooth limiter is no polynomial, and its largest ratio is 62.99.10-14​10-12​10-10​10-8​10-6​10-4​10-2​110-7​10-6​10-5​10-4​10-3​10-2​10-1​1Newton correction ‖ΔUk​‖∞next residual ‖R(Uk+1​)‖∞first orderunlimited linearsmooth limiter¼‖ΔU‖²(9/8)‖ΔU‖²
Figure 24 · Quadratic convergence at a glance: the correction ∥Δ𝐔k∥∞\|\Delta\mathbf U^k\|_\infty of every Newton step (horizontal) against the next residual ∥R(𝐔k+1)∥∞\|R(\mathbf U^{k+1})\|_\infty (vertical), all steps for N=8N=8 to 128 and the three reconstructions (points below the rounding floor left out). The dashed lines are the bounds proved above, 14∥Δ𝐔∥2\tfrac14\|\Delta\mathbf U\|^2 (first order) and 98∥Δ𝐔∥2\tfrac98\|\Delta\mathbf U\|^2 (unlimited linear): the points of these two reconstructions lie on or below their lines (largest ratios 0.250 and 0.444; on the log-log axes both lines have slope 2). The residual of the smooth limiter is no polynomial, and its largest ratio is 62.99.
图 25 · Newton 迭代的残差 ‖R(U^k)‖_∞(实线)与修正 ‖ΔU^k‖_∞(虚线),默认设计,N=8:一阶 5 次、无限制器线性 4 次、光滑限制器 6 次(计入最后那次只检查、不更新的迭代)。一阶与无限制器线性的指数大致每步翻倍(二次收敛),一直降到舍入误差的底线;光滑限制器的前两步慢得多。10-15​10-12​10-9​10-6​10-3​1012345Newton 迭代 k无穷范数停止:‖ΔU‖∞ ≤ 1e−13一阶无限制器线性光滑限制器实线 ‖R‖∞,虚线 ‖ΔU‖∞
图 25 · Newton 迭代的残差 ∥R(𝐔k)∥∞\|R(\mathbf U^k)\|_\infty(实线)与修正 ∥Δ𝐔k∥∞\|\Delta\mathbf U^k\|_\infty(虚线),默认设计,N=8N=8:一阶 5 次、无限制器线性 4 次、光滑限制器 6 次(计入最后那次只检查、不更新的迭代)。一阶与无限制器线性的指数大致每步翻倍(二次收敛),一直降到舍入误差的底线;光滑限制器的前两步慢得多。
Figure 25 · The residual ‖R(U^k)‖_∞ (solid) and the correction ‖ΔU^k‖_∞ (dashed) of the Newton iterations, default design, N=8: 5 iterations at first order, 4 for unlimited linear and 6 for the smooth limiter (counting the last one, which only checks and does not update). For first order and unlimited linear the exponent roughly doubles at each step (quadratic convergence) down to the rounding floor; the first two steps of the smooth limiter are much slower.10-15​10-12​10-9​10-6​10-3​1012345Newton iteration kmax normstop: ‖ΔU‖∞ ≤ 1e−13first orderunlimited linearsmooth limitersolid ‖R‖∞, dashed ‖ΔU‖∞
Figure 25 · The residual ∥R(𝐔k)∥∞\|R(\mathbf U^k)\|_\infty (solid) and the correction ∥Δ𝐔k∥∞\|\Delta\mathbf U^k\|_\infty (dashed) of the Newton iterations, default design, N=8N=8: 5 iterations at first order, 4 for unlimited linear and 6 for the smooth limiter (counting the last one, which only checks and does not update). For first order and unlimited linear the exponent roughly doubles at each step (quadratic convergence) down to the rounding floor; the first two steps of the smooth limiter are much slower.

下面的播放器每步一个 Newton 迭代:迭代值与精确节点值的对照、修正量、步长、残差,以及这一步的 Newton 矩阵 A(𝐔k)A(\mathbf U^k)(第 6 节的主题);表里还有整步之后的残差与二次余项的比较。

The player below takes one Newton iteration per step: the iterate against the exact nodal values, the correction, the step, the residual, and the Newton matrix A(𝐔k)A(\mathbf U^k) of this step (the subject of Section 6); the table also compares the residual after a full step with the quadratic remainder.

停止准则要考虑舍入误差的底线:∥Δ𝐔∥∞≤10−13\|\Delta\mathbf U\|_\infty\le10^{-13} 在细网格上不一定总能达到。本页 N=8N=8 到 4096、三种重构的全部 30 个 Newton 运行都按停止准则收敛了;全局控件的 NN 最大取到 128,更细的网格要用独立的带状程序。但在最细的网格上,准则恰在舍入允许的边缘:用同样的规则、另一套舍入的独立 Python 复现,在一阶、N=2048N=2048 时因为线搜索在舍入误差底线上找不到下降的步而提前停止,状态与本页的相同到舍入精度。所以 N≥2048N\ge2048 的迭代次数取决于舍入,不是格式的性质,本页不引用它们。

A stopping rule must allow for the rounding floor: ∥Δ𝐔∥∞≤10−13\|\Delta\mathbf U\|_\infty\le10^{-13} cannot always be reached on fine meshes. All 30 Newton runs of this page's study (N=8N=8 to 4096, three reconstructions) converged by the stopping rule; the global controls stop at N=128N=128, and finer meshes use the independent band program. On the finest meshes, however, the rule sits at the edge of what rounding allows: an independent Python replica with the same rules and other rounding stops first order at N=2048N=2048 early, because its line search finds no decreasing step on the rounding floor, with a state that agrees with this page's to rounding accuracy. The number of iterations at N≥2048N\ge2048 therefore depends on rounding and is not a property of the scheme; this page does not quote it.

格式的相容性

Consistency of the scheme

相容性要问的是:精确解代入离散方程后留下的误差,是否随加密而消失。下表把第 4 节的测量写成残差密度 Rj/hR_j/h(无限制器线性):内部行 O(h2)O(h^2),紧邻边界的两行 O(h)O(h),二者都趋于零,cHc_H 也趋于零。所以在通常的逐点意义上,这个格式每一行都是相容的,这与格心页不同(那里端行的密度趋于常数,格式靠通量差分形式才收敛)。一阶重构同样(所有行 O(h)O(h));光滑限制器在细网格上有两个边界行的密度趋于常数(第 4 节)。解的收敛要靠第 4 节的稳定性论证,而不只是相容性。

Consistency asks whether the exact solution satisfies the discrete equations up to an error that vanishes under refinement. The table writes the measurements of Section 4 as residual densities Rj/hR_j/h (unlimited linear): O(h2)O(h^2) inside and O(h)O(h) in the two rows next to the boundary, both tending to zero, and cHc_H tends to zero too. So in the usual pointwise sense every row of this scheme is consistent, unlike on the cell-centred page (where the densities of the end rows tend to constants and the scheme converges through its flux-difference form). First order is the same (every row O(h)O(h)); the smooth limiter has two boundary rows whose densities tend to constants on fine meshes (Section 4). The convergence of the solution rests on the stability argument of Section 4, not on consistency alone.

NNmax⁡2≤j≤N−2∣Rj∣/h\max_{2\le j\le N-2}|R_j|/hR1/hR_1/hRN−1/hR_{N-1}/hcHc_H
81.64e−1−2.63e−2−1.68e−1−4.81e−3
327.30e−3−3.37e−2−1.21e−25.82e−4
1284.14e−4−9.30e−3−3.32e−31.60e−5
5122.53e−5−2.38e−3−8.74e−4−4.80e−7
20481.59e−6−5.97e−4−2.22e−4−6.29e−8
40963.97e−7−2.99e−4−1.11e−4−1.72e−8
第 6 节Section 6

Jacobian 与 Gauss–Seidel

The Jacobian and Gauss–Seidel

本节实验:先数一数:在第 33 行,AA 的非零元素在一阶重构和无限制器线性重构时各有几个?第 00 行和第 11 行呢?再预测:Gauss–Seidel 能不能解 Newton 修正方程?N=8N=8 和 N=128N=128 各要几次扫描,是几次还是几百次?图 26、图 27、图 28 和下面的面板给出答案。

Experiment: Count first: how many nonzero entries does row 33 of AA have at first order and with unlimited linear reconstruction, and how many do rows 00 and 11 have? Then predict: does Gauss–Seidel converge on the Newton correction system, and how many sweeps does it need for N=8N=8 and for N=128N=128: a few, or hundreds? Figure 26, Figure 27, Figure 28 and the panels below answer.

第 5 节把 A=R𝐔A=R_{\mathbf U} 当作 Newton 法里的黑箱。本节把它造出来,看它的结构和可以证明的性质,再用 Gauss–Seidel(GS)近似地解 Newton 修正方程:以一阶矩阵作预处理,量出 GS 收敛得有多快。格点格式的 AA 有两个与格心页不同的特点:两个约束行是单位行,一阶矩阵在边界上没有特殊的行。

Section 5 used A=R𝐔A=R_{\mathbf U} as a black box inside Newton's method. This section builds it, looks at its structure and at the properties that can be proved, then solves the Newton correction system approximately with Gauss–Seidel (GS) on the first-order matrix and measures how fast GS converges. The node-centred AA differs from that of the cell-centred page in two ways: the two constraint rows are identity rows, and the first-order matrix has no special row at the boundary.

A=R𝐔A=R_{\mathbf U}:前向代码的列

A=R𝐔A=R_{\mathbf U} by columns of the forward code

第 jj 列是残差对 UjU_j 的单位变化的响应,也就是第 8 节的前向代码以种子 𝐔˙=ej\dot{\mathbf U}=e_j、D˙=0\dot D=0 的输出:N+1N+1 次前向求值得到整个矩阵(model.js 里的 jacState)。乘积不需要矩阵:一次前向求值就给出 AvAv(这里 vv 是任意向量,不是后面各节的切线解 vkv_k)。

Column jj of AA is the response of the residual to a unit change of UjU_j, that is, the output of the forward code of Section 8 with the seed 𝐔˙=ej\dot{\mathbf U}=e_j, D˙=0\dot D=0: N+1N+1 forward evaluations give the whole matrix (jacState in model.js). A product needs no matrix at all: one forward evaluation gives AvAv (here vv is any vector, not the tangent solutions vkv_k of the later sections).

A ej=R˙∣𝐔˙=ej, D˙=0,A v=R˙∣𝐔˙=v, D˙=0.A\,e_j=\dot R\Big|_{\dot{\mathbf U}=e_j,\ \dot D=0},\qquad A\,v=\dot R\Big|_{\dot{\mathbf U}=v,\ \dot D=0}.

验算:由组装好的矩阵算的 AvAv 与一次前向求值之差为 10−1410^{-14}(三种重构,N=8N=8)。还可以做得更好:第 jj 行只含 Uj−2,…,Uj+2U_{j-2},\dots,U_{j+2},所以相隔 5 的两列从不共用一行;按 jj 模 5 给列分组(每组一种“颜色”)、一组一组同时给种子,5 次前向求值就得到整条带,不论 NN 多大(与逐列组装的差为 0)。两个单位行只含自己,不破坏这个分组。本页的细网格计算(NN 到 4096)用这种方式组装带,再用带状 LU 求解。

Check: AvAv from the assembled matrix and from one forward evaluation differ by 10−1410^{-14} (all three reconstructions, N=8N=8). One can do even better: row jj involves only Uj−2,…,Uj+2U_{j-2},\dots,U_{j+2}, so two columns five apart never share a row; grouping the columns by jj mod 5 (one “colour” per group) and seeding each group at once, 5 forward evaluations give the whole band, whatever NN is (difference from the column-by-column assembly 0). The two identity rows involve only themselves and do not disturb the grouping. The fine-mesh computations of this page (NN up to 4096) assemble the band this way and solve with a band LU.

结构:单位行与五条对角线或三条

The structure: identity rows and five diagonals or three

第 00 行和第 NN 行是约束的单位行(第 4 节)。内部行 Rj=Hj−Hj−1−SjR_j=H_j-H_{j-1}-S_j:面 ff 含 Uf−1,…,Uf+2U_{f-1},\dots,U_{f+2}(无限制器线性、光滑限制器)或 Uf,Uf+1U_f,U_{f+1}(一阶,第 3 节),所以第 jj 行含 Uj−2,…,Uj+2U_{j-2},\dots,U_{j+2}(五条对角线)或 Uj−1,Uj,Uj+1U_{j-1},U_j,U_{j+1}(三条);边界面读的节点少一个(面 00 读 U0,U1,U2U_0,U_1,U_2,面 N−1N-1 读 UN−2,UN−1,UNU_{N-2},U_{N-1},U_N),所以二阶时第 11 行和第 N−1N-1 行只有四个非零元素。N=8N=8 时每行的非零个数:一阶 1、3、3、3、3、3、3、3、1,无限制器线性与光滑限制器 1、4、5、5、5、5、5、4、1;总共 23(=3(N−1)+2=3(N-1)+2)与 35(=5(N−3)+2⋅4+2=5(N-3)+2\cdot4+2)个。一阶时第 33 行有 3 个,二阶时 5 个。

Rows 00 and NN are the identity rows of the constraints (Section 4). An interior row is Rj=Hj−Hj−1−SjR_j=H_j-H_{j-1}-S_j: face ff involves Uf−1,…,Uf+2U_{f-1},\dots,U_{f+2} (unlimited linear, smooth limiter) or Uf,Uf+1U_f,U_{f+1} (first order, Section 3), so row jj involves Uj−2,…,Uj+2U_{j-2},\dots,U_{j+2} (five diagonals) or Uj−1,Uj,Uj+1U_{j-1},U_j,U_{j+1} (three diagonals); the boundary faces read one node fewer (face 00 reads U0,U1,U2U_0,U_1,U_2 and face N−1N-1 reads UN−2,UN−1,UNU_{N-2},U_{N-1},U_N), so at second order rows 11 and N−1N-1 have only four nonzero entries. The number of nonzeros of each row at N=8N=8: 1, 3, 3, 3, 3, 3, 3, 3, 1 at first order, 1, 4, 5, 5, 5, 5, 5, 4, 1 for unlimited linear and the smooth limiter; in all 23 (=3(N−1)+2=3(N-1)+2) and 35 (=5(N−3)+2⋅4+2=5(N-3)+2\cdot4+2). Row 33 has 3 at first order and 5 at second order.

一阶时第 3 节写出的内部行是黏性 ν+h\nu+h 的中心格式:

At first order the interior row written in Section 3 is the central scheme for the viscosity ν+h\nu+h:

Rj=14(Uj+12−Uj−12)−(1+νh)(Uj+1−2Uj+Uj−1)−Sj.R_j=\tfrac14\bigl(U_{j+1}^2-U_{j-1}^2\bigr)-\Bigl(1+\frac\nu h\Bigr)\bigl(U_{j+1}-2U_j+U_{j-1}\bigr)-S_j.

逐项求导,得到 Jacobian 的行;每一个内部行(包括第 11 行和第 N−1N-1 行)都是这个公式,边界上没有特殊的行,第 11 行的 A1,0A_{1,0} 乘的是边界节点的值:

Differentiating it term by term gives the row of the Jacobian; every interior row, rows 11 and N−1N-1 included, is this formula, nothing is special at the boundary, and the A1,0A_{1,0} of row 11 multiplies the value of the boundary node:

Aj,j−1=−(Uj−12+1+νh),Ajj=2(1+νh),Aj,j+1=Uj+12−1−νh(1≤j≤N−1).A_{j,j-1}=-\Bigl(\frac{U_{j-1}}2+1+\frac\nu h\Bigr),\qquad A_{jj}=2\Bigl(1+\frac\nu h\Bigr),\qquad A_{j,j+1}=\frac{U_{j+1}}2-1-\frac\nu h\qquad(1\le j\le N-1).

格心页不同:那里第一行和最后一行是 A00=2+3ν/hA_{00}=2+3\nu/h 这样的特殊公式。这些公式与前向代码组装的 AA 一致(收敛解处与 Newton 初值处,每个内部行;最大差为 0)。

The cell-centred page differs: there the first and the last row are special formulas such as A00=2+3ν/hA_{00}=2+3\nu/h. These formulas agree with the AA assembled by the forward code (at the converged solution and at the Newton initial guess, every interior row; the largest difference is 0).

图 26 · 三种重构的矩阵 A=R_(U)(默认设计的收敛解,N=8),蓝色为正、橙色为负,格子里是数值。第 0 行和第 N 行是单位行;一阶是三对角(内部行),无限制器线性与光滑限制器有五条对角线(第 1 行和第 N-1 行只有四个元素)。无限制器线性的两条外对角线全为正(c_L/4 与 -c_R/4);光滑限制器的外对角线带着斜率导数 σ_l,σ_r,正负都可以(这里的外对角线上有 8 个正元素、4 个负元素)。一阶1.00−1.542.16−0.56−1.592.16−0.60−1.602.16−0.67−1.562.16−0.72−1.492.16−0.72−1.442.16−0.68−1.442.16−0.621.00012345678012345678无限制器线性1.00−1.101.37−0.240.110.39−1.941.69−0.190.100.40−1.971.62−0.230.110.39−1.911.58−0.330.130.37−1.811.58−0.430.140.36−1.711.63−0.470.150.35−1.691.55−0.151.00012345678012345678光滑限制器1.00−0.921.12−0.040.020.14−0.991.02−0.17−1e−3−0.13−2.172.58−0.380.040.97−3.072.43−0.760.280.64−2.101.59−0.28−4e−30.05−0.721.01−0.360.01−0.15−1.812.36−0.341.00012345678012345678
图 26 · 三种重构的矩阵 A=R𝐔A=R_{\mathbf U}(默认设计的收敛解,N=8N=8),蓝色为正、橙色为负,格子里是数值。第 00 行和第 NN 行是单位行;一阶是三对角(内部行),无限制器线性与光滑限制器有五条对角线(第 11 行和第 N−1N-1 行只有四个元素)。无限制器线性的两条外对角线全为正(cL/4c_L/4 与 −cR/4-c_R/4);光滑限制器的外对角线带着斜率导数 σl,σr\sigma_l,\sigma_r,正负都可以(这里的外对角线上有 8 个正元素、4 个负元素)。
Figure 26 · The matrix A=R_(U) of the three reconstructions (converged solution of the default design, N=8), blue positive and orange negative, values in the cells. Rows 0 and N are identity rows; first order is tridiagonal (interior rows), unlimited linear and the smooth limiter have five diagonals (rows 1 and N-1 only four entries). The two outer diagonals of unlimited linear are all positive (c_L/4 and -c_R/4); those of the smooth limiter carry the slope derivatives σ_l,σ_r and have either sign (here 8 positive and 4 negative entries on the outer diagonals).first order1.00−1.542.16−0.56−1.592.16−0.60−1.602.16−0.67−1.562.16−0.72−1.492.16−0.72−1.442.16−0.68−1.442.16−0.621.00012345678012345678unlimited linear1.00−1.101.37−0.240.110.39−1.941.69−0.190.100.40−1.971.62−0.230.110.39−1.911.58−0.330.130.37−1.811.58−0.430.140.36−1.711.63−0.470.150.35−1.691.55−0.151.00012345678012345678smooth limiter1.00−0.921.12−0.040.020.14−0.991.02−0.17−1e−3−0.13−2.172.58−0.380.040.97−3.072.43−0.760.280.64−2.101.59−0.28−4e−30.05−0.721.01−0.360.01−0.15−1.812.36−0.341.00012345678012345678
Figure 26 · The matrix A=R𝐔A=R_{\mathbf U} of the three reconstructions (converged solution of the default design, N=8N=8), blue positive and orange negative, values in the cells. Rows 00 and NN are identity rows; first order is tridiagonal (interior rows), unlimited linear and the smooth limiter have five diagonals (rows 11 and N−1N-1 only four entries). The two outer diagonals of unlimited linear are all positive (cL/4c_L/4 and −cR/4-c_R/4); those of the smooth limiter carry the slope derivatives σl,σr\sigma_l,\sigma_r and have either sign (here 8 positive and 4 negative entries on the outer diagonals).

在下面的面板里选择重构(NN 由全局控件决定),看 AA、一阶矩阵 PP、二者之差和 A−1A^{-1} 的符号;还可以只看内部块 AIIA_{\rm II}:

In the panel below change the reconstruction (NN is set by the global controls) and look at AA, the first-order matrix PP, their difference and the signs of A−1A^{-1}; the interior block AIIA_{\rm II} can be shown alone:

关于 AA 能说什么

What can be said about AA

分块结构。把未知量排成 U0U_0、内部未知量 UI=(U1,…,UN−1)U_{\rm I}=(U_1,\dots,U_{N-1})、UNU_N,单位行使 AA 成为分块矩阵

Block structure. Ordering the unknowns as U0U_0, the interior unknowns UI=(U1,…,UN−1)U_{\rm I}=(U_1,\dots,U_{N-1}) and UNU_N, the identity rows make AA a block matrix

A=(100AI0AIIAIN001),A−1=(100−AII−1AI0AII−1−AII−1AIN001),A=\begin{pmatrix}1&0&0\\ A_{{\rm I}0}&A_{\rm II}&A_{{\rm I}N}\\ 0&0&1\end{pmatrix},\qquad A^{-1}=\begin{pmatrix}1&0&0\\ -A_{\rm II}^{-1}A_{{\rm I}0}&A_{\rm II}^{-1}&-A_{\rm II}^{-1}A_{{\rm I}N}\\ 0&0&1\end{pmatrix},

AI0,AINA_{{\rm I}0},A_{{\rm I}N} 是边界节点 00 与 NN 的列(落在内部行里的部分)。于是 det⁡A=det⁡AII\det A=\det A_{\rm II},AA 的特征值是 1,11,1 和 AIIA_{\rm II} 的特征值,Ax=rAx=r 的解是 x0=r0x_0=r_0,xN=rNx_N=r_N,AIIxI=rI−AI0 r0−AIN rNA_{\rm II}x_{\rm I}=r_{\rm I}-A_{{\rm I}0}\,r_0-A_{{\rm I}N}\,r_N:约束行与内部方程解耦。Newton 法里 r0=rN=0r_0=r_N=0(第 5 节),每一步只解 AIIΔUI=−RIA_{\rm II}\Delta U_{\rm I}=-R_{\rm I};下面的 GS 也只作用在这个内部块上。(第 11 节的转置方程 ATψ=−gA^T\psi=-g 同样解耦:内部的 ψI\psi_{\rm I} 满足 AIITψI=−gIA_{\rm II}^T\psi_{\rm I}=-g_{\rm I},然后 ψ0=−g0−AI0TψI\psi_0=-g_0-A_{{\rm I}0}^T\psi_{\rm I},ψN\psi_N 类似。)

where AI0,AINA_{{\rm I}0},A_{{\rm I}N} are the columns of the boundary nodes 00 and NN (the part that lies in the interior rows). So det⁡A=det⁡AII\det A=\det A_{\rm II}, the eigenvalues of AA are 1,11,1 and those of AIIA_{\rm II}, and the solution of Ax=rAx=r is x0=r0x_0=r_0, xN=rNx_N=r_N, AIIxI=rI−AI0 r0−AIN rNA_{\rm II}x_{\rm I}=r_{\rm I}-A_{{\rm I}0}\,r_0-A_{{\rm I}N}\,r_N: the constraint rows decouple from the interior equations. In Newton's method r0=rN=0r_0=r_N=0 (Section 5), every step solves AIIΔUI=−RIA_{\rm II}\Delta U_{\rm I}=-R_{\rm I} only, and the GS below acts on this interior block only. (The transposed system ATψ=−gA^T\psi=-g of Section 11 decouples in the same way: the interior ψI\psi_{\rm I} satisfies AIITψI=−gIA_{\rm II}^T\psi_{\rm I}=-g_{\rm I}, and then ψ0=−g0−AI0TψI\psi_0=-g_0-A_{{\rm I}0}^T\psi_{\rm I}, similarly ψN\psi_N.)

符号。一阶时,只要 ∣U∣<2|U|<2(Newton 的范围 0.1<U<1.90.1<U<1.9 保证了这一点),所有非对角元素为负、对角元素为正:AA 与 AIIA_{\rm II} 都是 Z 矩阵(没有正的非对角元素)。有重构时外对角线出现:无限制器线性的 Aj,j−2=cL(j−1)/4>0A_{j,j-2}=c_L(j-1)/4>0、Aj,j+2=−cR(j)/4>0A_{j,j+2}=-c_R(j)/4>0,所以出现正的非对角元素(N=8N=8 时 AA 里有 12 个,AIIA_{\rm II} 里有 10 个),AA 不再是 Z 矩阵;光滑限制器的外对角线带着 σl,σr\sigma_l,\sigma_r,正负都可以(AA 里有 8 个正的非对角元素)。

Signs. At first order, as long as ∣U∣<2|U|<2 (Newton's range 0.1<U<1.90.1<U<1.9 guarantees it), every off-diagonal entry is negative and every diagonal entry positive: AA and AIIA_{\rm II} are Z-matrices (no positive off-diagonal entry). With reconstruction the outer diagonals appear: for unlimited linear Aj,j−2=cL(j−1)/4>0A_{j,j-2}=c_L(j-1)/4>0 and Aj,j+2=−cR(j)/4>0A_{j,j+2}=-c_R(j)/4>0, so positive off-diagonal entries appear (12 in AA and 10 in AIIA_{\rm II} at N=8N=8) and AA is no longer a Z-matrix; for the smooth limiter the outer diagonals carry σl,σr\sigma_l,\sigma_r and have either sign (8 positive off-diagonal entries in AA).

行和。一阶内部行的行和是 (Uj+1−Uj−1)/2(U_{j+1}-U_{j-1})/2,解下降的地方为负:AIIA_{\rm II} 不是行对角占优的(一阶,N=8N=8,AIIA_{\rm II} 的行和从 −0.119 到 1.601)。

Row sums. The row sum of a first-order interior row is (Uj+1−Uj−1)/2(U_{j+1}-U_{j-1})/2, negative where the solution decreases: AIIA_{\rm II} is not diagonally dominant by rows (at first order, N=8N=8, the row sums of AIIA_{\rm II} range from −0.119 to 1.601).

列和。守恒体现在列和里:把内部行 1,…,N−11,\dots,N-1 加起来,∑j=1N−1Ajk=∂(HN−1−H0)/∂Uk\sum_{j=1}^{N-1}A_{jk}=\partial(H_{N-1}-H_0)/\partial U_k(第 5 节的守恒)。两个边界面只读边界附近的节点(一阶读 U0,U1U_0,U_1 与 UN−1,UNU_{N-1},U_N,二阶读 U0,U1,U2U_0,U_1,U_2 与 UN−2,UN−1,UNU_{N-2},U_{N-1},U_N),所以只有这些列的和不为零。实测 N=8N=8:一阶的非零列是 0、1、7、8,无限制器线性与光滑限制器是 0、1、2、6、7、8(其余列的和不超过 5×10−155\times10^{-15})。对 AIIA_{\rm II} 起作用的是一阶的两个:

Column sums. Conservation shows in the column sums: adding the interior rows 1,…,N−11,\dots,N-1 gives ∑j=1N−1Ajk=∂(HN−1−H0)/∂Uk\sum_{j=1}^{N-1}A_{jk}=\partial(H_{N-1}-H_0)/\partial U_k (the conservation of Section 5). The two boundary faces read only nodes near the boundary (first order U0,U1U_0,U_1 and UN−1,UNU_{N-1},U_N, second order U0,U1,U2U_0,U_1,U_2 and UN−2,UN−1,UNU_{N-2},U_{N-1},U_N), so only these columns have a nonzero sum. Measured at N=8N=8: the nonzero columns are 0, 1, 7, 8 at first order and 0, 1, 2, 6, 7, 8 for unlimited linear and the smooth limiter (the other columns sum to at most 5×10−155\times10^{-15}). The two that matter for AIIA_{\rm II} at first order are:

∑i=1N−1(AII)i1=1+νh−U12>0,∑i=1N−1(AII)i,N−1=1+νh+UN−12>0,AII 的其余各列之和为零。\sum_{i=1}^{N-1}(A_{\rm II})_{i1}=1+\frac\nu h-\frac{U_1}2>0,\qquad\sum_{i=1}^{N-1}(A_{\rm II})_{i,N-1}=1+\frac\nu h+\frac{U_{N-1}}2>0,\qquad A_{\rm II}\text{ 的其余各列之和为零。}
∑i=1N−1(AII)i1=1+νh−U12>0,∑i=1N−1(AII)i,N−1=1+νh+UN−12>0,all other column sums of AII vanish.\sum_{i=1}^{N-1}(A_{\rm II})_{i1}=1+\frac\nu h-\frac{U_1}2>0,\qquad\sum_{i=1}^{N-1}(A_{\rm II})_{i,N-1}=1+\frac\nu h+\frac{U_{N-1}}2>0,\qquad\text{all other column sums of }A_{\rm II}\text{ vanish.}

实测(一阶,N=8N=8):第 11 列的和是 0.568912(公式 0.568912),第 N−1N-1 列是 1.475199(公式 1.475199)。

Measured (first order, N=8N=8): column 11 sums to 0.568912 (formula 0.568912), column N−1N-1 to 1.475199 (formula 1.475199).

一阶的 AIIA_{\rm II} 是 M 矩阵。定理(Varga):设 MM 是对角元素为正的 Z 矩阵。若 MM 不可约,按行弱对角占优,并且至少在一行严格对角占优,则 MM 非奇异,且 M−1M^{-1} 的每个元素都是正的。

At first order AIIA_{\rm II} is an M-matrix. Theorem (Varga). Let MM be a Z-matrix with positive diagonal. If MM is irreducible, weakly diagonally dominant by rows and strictly diagonally dominant in at least one row, then MM is nonsingular and every entry of M−1M^{-1} is positive.

证明(一阶):AIITA_{\rm II}^T 也是对角元素为正的 Z 矩阵,它的行和就是 AIIA_{\rm II} 的列和:第 2,…,N−22,\dots,N-2 列为 00,第 11 列和第 N−1N-1 列为正(上面的两个公式)。对 Z 矩阵,行和非负恰好就是按行弱对角占优,所以 AIITA_{\rm II}^T 按行弱对角占优,在两行严格占优。AIIA_{\rm II} 是三对角矩阵,上、下对角元素都不为零,所以 AIITA_{\rm II}^T 不可约。由定理 (AIIT)−1>0(A_{\rm II}^T)^{-1}>0,即 AII−1>0A_{\rm II}^{-1}>0。对每个 0.1<U<1.90.1<U<1.9 的状态都成立。整个 AA 是可约的(两个单位行与其余部分不相连),但由分块公式,AI0≤0A_{{\rm I}0}\le0、AIN≤0A_{{\rm I}N}\le0(只有 A1,0A_{1,0} 与 AN−1,NA_{N-1,N} 非零,都是负的)和 AII−1>0A_{\rm II}^{-1}>0 得 A−1≥0A^{-1}\ge0:AA 是(可约的)M 矩阵。实测:AII−1A_{\rm II}^{-1} 的最小元素是 2.88e−3(N=8N=8),N=128N=128 时是 7.6e−26,仍为正(远离对角线的元素按因子连乘衰减),没有一个负元素(相对容差 10−1010^{-10})。

Proof (first order): AIITA_{\rm II}^T is also a Z-matrix with positive diagonal, and its row sums are the column sums of AIIA_{\rm II}: 00 for columns 2,…,N−22,\dots,N-2, positive for columns 11 and N−1N-1 (the two formulas above). For such a matrix a nonnegative row sum is exactly weak diagonal dominance, so AIITA_{\rm II}^T is weakly diagonally dominant by rows, strictly in two rows. AIIA_{\rm II} is tridiagonal with nonzero sub- and superdiagonal entries, so AIITA_{\rm II}^T is irreducible. By the theorem (AIIT)−1>0(A_{\rm II}^T)^{-1}>0, that is AII−1>0A_{\rm II}^{-1}>0. This holds for every state with 0.1<U<1.90.1<U<1.9. The whole AA is reducible (the two identity rows are not connected to the rest), but the block formula, AI0≤0A_{{\rm I}0}\le0, AIN≤0A_{{\rm I}N}\le0 (only A1,0A_{1,0} and AN−1,NA_{N-1,N} are nonzero, both negative) and AII−1>0A_{\rm II}^{-1}>0 give A−1≥0A^{-1}\ge0: AA is a (reducible) M-matrix. Measured: the smallest entry of AII−1A_{\rm II}^{-1} is 2.88e−3 at N=8N=8 and 7.6e−26 at N=128N=128, still positive (entries far from the diagonal decay like a product of factors), and there is no negative entry (relative tolerance 10−1010^{-10}).

二阶时 AA 不是 Z 矩阵,定理不适用。N=8N=8 时无限制器线性的 AII−1A_{\rm II}^{-1} 有 11 个负元素,最小是 −0.0812;N=8,16,32,64N=8,16,32,64 的负元素个数是 11、57、193、442,到 N=128N=128 时没有超过舍入水平的负元素(相对容差 10−1010^{-10})。光滑限制器:11、47、186、446、0(N=8,16,32,64,128N=8,16,32,64,128)。所以二阶的 AII−1A_{\rm II}^{-1} 在对流占优的粗网格上有负元素,但并不总是如此。

At second order AA is not a Z-matrix and the theorem does not apply. At N=8N=8 the AII−1A_{\rm II}^{-1} of unlimited linear has 11 negative entries, the smallest −0.0812; for N=8,16,32,64N=8, 16, 32, 64 the number of negative entries is 11, 57, 193, 442, and at N=128N=128 there is none above the rounding level (relative tolerance 10−1010^{-10}). The smooth limiter: 11, 47, 186, 446, 0 for N=8,16,32,64,128N=8, 16, 32, 64, 128. So the inverse of the second-order AIIA_{\rm II} has negative entries on coarse convection-dominated meshes, but not always.

条件数。cond⁡1(A)=∥A∥1∥A−1∥1\operatorname{cond}_1(A)=\|A\|_1\|A^{-1}\|_1(用带状 LU 逐列精确算出,不是估计)随 NN 增长,表中是默认设计的收敛解(单位行的比例是 1):无限制器线性从 N=8N=8 的 37.71 增长到 N=1024N=1024 的 4.413e4;最后一次加密乘以 3.67,趋向扩散算子的 N2N^2(每次加密乘以 4);粗网格上对流占优,增长较慢。内部块 AIIA_{\rm II} 的条件数与它相差不大(一阶 N=8N=8:25.01 对 35.72;N≥256N\ge256 时前四位相同):约束行的单位比例没有恶化问题。LU 求解不在乎(误差约为 cond⁡1(A)⋅10−16\operatorname{cond}_1(A)\cdot10^{-16}),但迭代法会变慢,下面就看到。

Condition number. cond⁡1(A)=∥A∥1∥A−1∥1\operatorname{cond}_1(A)=\|A\|_1\|A^{-1}\|_1 (computed exactly column by column with the band LU, not estimated) grows with NN; the table is for the converged solution of the default design (the identity rows have scale 1): for unlimited linear it grows from 37.71 at N=8N=8 to 4.413e4 at N=1024N=1024; the last doubling multiplies it by 3.67, approaching the N2N^2 of a diffusion operator (a factor of 4 per doubling); on coarse meshes convection dominates and the growth is slower. The condition number of the interior block AIIA_{\rm II} is close (first order N=8N=8: 25.01 against 35.72; the first four digits agree for N≥256N\ge256): the unit scale of the constraint rows does no harm. LU solves do not care (their error is about cond⁡1(A)⋅10−16\operatorname{cond}_1(A)\cdot10^{-16}), but iterative methods slow down, as we see next.

NN一阶first order无限制器线性unlimited linear光滑限制器smooth limiter
83.572e13.771e15.489e1
167.673e18.387e11.245e2
321.675e21.775e22.337e2
644.048e24.126e24.546e2
1281.109e31.121e31.145e3
2563.448e33.495e33.494e3
5121.193e41.201e41.196e4
10244.397e44.413e44.399e4

用一阶矩阵做 Gauss–Seidel

Gauss–Seidel with the first-order matrix

LU 精确地解 AIIΔUI=−RIA_{\rm II}\Delta U_{\rm I}=-R_{\rm I}(稠密 O(N3)O(N^3),带状 O(N)O(N))。经典的替代做法是迭代:每一步只需要一个便宜的近似求解。为了与第 17 节一致,这里把线性方程组写成 Ax=bAx=b(AA 即 AIIA_{\rm II}),迭代值记作 xmx^m(迭代次数 mm),精确解 x∗x^*,缺陷 r=b−Axr=b-Ax(线性方程组的残差);它们与坐标 xx、第 3 节的单侧差分 lj,rjl_j,r_j 没有关系。取同一状态下的一阶 Jacobian 的内部块 PP(三对角),拆成对角、严格下三角和严格上三角 P=diag⁡(P)+P−+P+P=\operatorname{diag}(P)+P_-+P_+(写成 P±P_\pm 以免与状态 𝐔\mathbf U 混淆)。在 PP 上从零开始做一次前向 GS 扫描,就是逐行解下三角方程组 (diag⁡(P)+P−) Δx=r(\operatorname{diag}(P)+P_-)\,\Delta x=r,记作 Δx=Br\Delta x=Br(这里 BB 是 GS 映射,与附录 B 无关)。缺陷校正是

LU solves AIIΔUI=−RIA_{\rm II}\Delta U_{\rm I}=-R_{\rm I} exactly (dense O(N3)O(N^3), banded O(N)O(N)). The classical alternative is an iteration that needs only a cheap approximate solve at each step. To match Section 17, this section writes the linear system as Ax=bAx=b (AA meaning AIIA_{\rm II}), with the iterates xmx^m (iteration counter mm), the exact solution x∗x^* and the defect r=b−Axr=b-Ax (the residual of the linear system); they have nothing to do with the coordinate xx or the one-sided differences lj,rjl_j,r_j of Section 3. Take the interior block PP of the first-order Jacobian at the same state (tridiagonal) and split it into its diagonal, strictly lower and strictly upper parts, P=diag⁡(P)+P−+P+P=\operatorname{diag}(P)+P_-+P_+ (written P±P_\pm so as not to clash with the state 𝐔\mathbf U). One forward GS sweep on PP from zero solves the lower-triangular system (diag⁡(P)+P−) Δx=r(\operatorname{diag}(P)+P_-)\,\Delta x=r row by row; call this map Δx=Br\Delta x=Br (here BB is the GS map; it has nothing to do with Appendix B). Defect correction is

xm+1=xm+ω B(b−Axm),B=(diag⁡(P)+P−)−1,xm+1−x∗=E (xm−x∗),E=I−ωBA.x^{m+1}=x^m+\omega\,B\bigl(b-Ax^m\bigr),\qquad B=\bigl(\operatorname{diag}(P)+P_-\bigr)^{-1},\qquad x^{m+1}-x^*=E\,(x^m-x^*),\quad E=I-\omega BA.
缺陷校正:用 P_II(一阶 Jacobian)和松弛因子 omega 解 A_II x = b
 x = 0
 for m = 0, 1, 2, ...:
   r = b - A_II x                                  缺陷(只需要乘积 A_II x)
   if ||r||_inf <= tol: stop
   for i = 1 .. N-1:                               在 P_II 上做一次从 dx = 0 开始的前向 GS 扫描
     dx_i = (r_i - P_{i,i-1} dx_{i-1}) / P_ii         (P 是三对角:只有 j = i-1)
   x = x + omega dx
defect correction: solve A_II x = b with P_II (the first-order Jacobian) and the relaxation omega
 x = 0
 for m = 0, 1, 2, ...:
   r = b - A_II x                                  defect (needs the product A_II x only)
   if ||r||_inf <= tol: stop
   for i = 1 .. N-1:                               one forward GS sweep on P_II, from dx = 0
     dx_i = (r_i - P_{i,i-1} dx_{i-1}) / P_ii         (P is tridiagonal: only j = i-1)
   x = x + omega dx

一阶时(A=PA=P)取 ω=1\omega=1,这就是 AA 上的 Gauss–Seidel:(diag⁡(P)+P−) xm+1=b−P+xm(\operatorname{diag}(P)+P_-)\,x^{m+1}=b-P_+x^m,误差传播矩阵 E=−(diag⁡(P)+P−)−1P+E=-(\operatorname{diag}(P)+P_-)^{-1}P_+。因为 PP 是 M 矩阵(上面),diag⁡(P)+P−\operatorname{diag}(P)+P_- 也是 M 矩阵,逆非负;又 −P+≥0-P_+\ge0,所以 E≥0E\ge0。由 Perron–Frobenius,谱半径 ρ(E)\rho(E)(本节里 ρ\rho 一律表示谱半径;附录 B 里的 ρ\rho 是另一个量)本身是 EE 的特征值,有非负特征向量(最慢的误差模态)。它还是模为 ρ\rho 的唯一特征值:三对角 PP 的 Jacobi 矩阵相似于零对角、次对角元素非零的对称三对角矩阵,特征值成对 ±μk\pm\mu_k 且都是单根,而 EE 的非零特征值是 μk2\mu_k^2,其余是零。这个分裂是 M 矩阵的正则分裂,由 Varga 定理 ρ(E)<1\rho(E)<1:在一阶方程组上,GS 对每个 NN 和每个 0.1<U<1.90.1<U<1.9 的状态都收敛。EE 的最小元素是 0(它的第一列全为零:P+P_+ 的第一列是零)。

At first order (A=PA=P) with ω=1\omega=1 this is Gauss–Seidel on AA: (diag⁡(P)+P−) xm+1=b−P+xm(\operatorname{diag}(P)+P_-)\,x^{m+1}=b-P_+x^m, with the error propagator E=−(diag⁡(P)+P−)−1P+E=-(\operatorname{diag}(P)+P_-)^{-1}P_+. Since PP is an M-matrix (above), diag⁡(P)+P−\operatorname{diag}(P)+P_- is an M-matrix too, with a nonnegative inverse; and −P+≥0-P_+\ge0, so E≥0E\ge0. By Perron–Frobenius, the spectral radius ρ(E)\rho(E) (in this section ρ\rho always denotes a spectral radius; Appendix B uses ρ\rho for another quantity) is itself an eigenvalue of EE, with a nonnegative eigenvector (the slowest error mode). It is also the only eigenvalue of modulus ρ\rho: the Jacobi matrix of the tridiagonal PP is similar to a symmetric tridiagonal matrix with zero diagonal and nonzero off-diagonal entries, whose eigenvalues come in pairs ±μk\pm\mu_k and are all simple, and the nonzero eigenvalues of EE are the μk2\mu_k^2, the others zero. The splitting is a regular splitting of an M-matrix, so ρ(E)<1\rho(E)<1 by Varga's theorem: on the first-order system GS converges for every NN and every state with 0.1<U<1.90.1<U<1.9. The smallest entry of EE is 0 (its first column is zero: the first column of P+P_+ is zero).

有多快?实测 ρ(E)\rho(E)(默认设计的收敛解,ω=1\omega=1;一阶由 Jacobi 特征值精确算出,其余由 QR 算法)见下表,一阶随 NN 趋于 1。把误差降到初值的 10−1010^{-10} 倍需要 ln⁡10−10/ln⁡ρ\ln10^{-10}/\ln\rho 次扫描:一阶 N=8N=8 时 80 次,N=128N=128 时 659 次。GS 在细网格上很慢。

How fast? The measured ρ(E)\rho(E) (converged solution of the default design, ω=1\omega=1; exact from the Jacobi eigenvalues at first order, by the QR algorithm otherwise) is in the table; at first order it tends to 1 with NN. Reducing the error to 10−1010^{-10} of its initial size takes ln⁡10−10/ln⁡ρ\ln10^{-10}/\ln\rho sweeps: 80 at first order for N=8N=8 and 659 for N=128N=128. GS is slow on fine meshes.

NN一阶first order无限制器线性unlimited linear光滑限制器smooth limiter
80.74960.62110.6819 *
160.83610.6740 *0.7338 *
320.88680.7558 *0.7757 *
640.93130.87350.9001
1280.96560.94780.9599

表中带 * 的是模最大的特征值为一对复数的情形。二阶时(A≠PA\ne P)E=I−BAE=I-BA 不再是非负的(N=8N=8 的无限制器线性,最小元素 −0.0670),没有定理保证收敛。默认设计下实测的 ρ(E)\rho(E) 处处小于 1,而且在每个 NN 上都小于一阶的值:迭代收敛,比一阶快;复数对出现在:无限制器线性 N=16,32N=16,32,光滑限制器 N=8,16,32N=8,16,32。这是一个设计下的测量,不是保证。

An asterisk marks the cases where the eigenvalues of largest modulus are a complex pair. At second order (A≠PA\ne P) E=I−BAE=I-BA is no longer nonnegative (smallest entry −0.0670 for unlimited linear at N=8N=8) and no theorem guarantees convergence. At the default design the measured ρ(E)\rho(E) is below 1 throughout and below the first-order value at every NN: the iteration converges, faster than at first order; the complex pairs occur for unlimited linear at N=16,32N=16,32 and for the smooth limiter at N=8,16,32N=8,16,32. These are measurements at one design, not a guarantee.

松弛。Eω=I−ωBA=(1−ω)I+ωE1E_\omega=I-\omega BA=(1-\omega)I+\omega E_1。一阶时 E1E_1 的特征值是实数,落在 [0,ρ(E1)][0,\rho(E_1)](它们是 Jacobi 特征值的平方 μk2\mu_k^2,以及 00),所以 ρ(Eω)=max⁡(∣1−ω∣, 1−ω(1−ρ(E1)))\rho(E_\omega)=\max\bigl(|1-\omega|,\,1-\omega(1-\rho(E_1))\bigr),在 ω∗=2/(2−ρ(E1))\omega^*=2/(2-\rho(E_1)) 处最小(第一个 Newton 修正方程上:N=8N=8 时 1.53,N=128N=128 时 1.93):精确算术下超松弛更快。在这个方程上 ω=1.3\omega=1.3 需要 49、143、596 次扫描(一阶)与 38、81、423 次(无限制器线性)(N=8,32,128N=8,32,128),在每种情形都比 ω=1\omega=1(68、189、779 与 53、111、553)少。但是不能只看 ρ\rho 来加大 ω\omega:E1E_1 的零特征值是亏损的(代数重数 N/2N/2,只有一个特征向量),ω>1\omega>1 时它移到 1−ω<01-\omega<0,迭代可能先增长许多个数量级再衰减:N=128N=128、ω=1.8\omega=1.8 时 ρ(Eω)=0.937\rho(E_\omega)=0.937,缺陷却在 131 次扫描内超过 10810^8(计算在此停止)。双精度下 ω∗\omega^* 本身在 N=64,128N=64,128 不收敛;在 ω=1.00,1.05,…,1.90\omega=1.00,1.05,\dots,1.90 的网格上,一阶最快的收敛 ω\omega 是 1.45、1.60、1.60、1.65(N=8,32,64,128N=8,32,64,128,扫描 43、115、214、467 次)。

Relaxation. Eω=I−ωBA=(1−ω)I+ωE1E_\omega=I-\omega BA=(1-\omega)I+\omega E_1. At first order the eigenvalues of E1E_1 are real and lie in [0,ρ(E1)][0,\rho(E_1)] (they are the squares μk2\mu_k^2 of the Jacobi eigenvalues, and 00), so ρ(Eω)=max⁡(∣1−ω∣, 1−ω(1−ρ(E1)))\rho(E_\omega)=\max\bigl(|1-\omega|,\,1-\omega(1-\rho(E_1))\bigr), smallest at ω∗=2/(2−ρ(E1))\omega^*=2/(2-\rho(E_1)) (on the first Newton correction system 1.53 at N=8N=8 and 1.93 at N=128N=128): in exact arithmetic over-relaxation helps. On this system ω=1.3\omega=1.3 needs 49, 143, 596 sweeps at first order and 38, 81, 423 for unlimited linear (N=8,32,128N=8,32,128), fewer than ω=1\omega=1 in every case (68, 189, 779 and 53, 111, 553). But ω\omega cannot be raised by looking at ρ\rho alone: the zero eigenvalue of E1E_1 is defective (algebraic multiplicity N/2N/2, a single eigenvector), for ω>1\omega>1 it moves to 1−ω<01-\omega<0, and the iteration can grow by many orders of magnitude before it decays: at N=128N=128 and ω=1.8\omega=1.8 one has ρ(Eω)=0.937\rho(E_\omega)=0.937, yet the defect exceeds 10810^8 within 131 sweeps (where the computation stops). In double precision ω∗\omega^* itself does not converge at N=64,128N=64,128; on the grid ω=1.00,1.05,…,1.90\omega=1.00,1.05,\dots,1.90 the fastest convergent ω\omega at first order is 1.45, 1.60, 1.60, 1.65 for N=8,32,64,128N=8,32,64,128 (43, 115, 214, 467 sweeps).

图 27 · 左:GS 缺陷校正的误差传播矩阵 E=I-BA_II 的谱半径(ω=1,默认设计的收敛解;一阶由 Jacobi 特征值 μ_k^2 精确算出,其余由 QR 算法)。三种重构的 ρ 都随 N 趋于 1。右:cond_1(A);虚线是正比于 N 与 N^2 的参考线。0.50.60.70.80.9110100Nρ(E)GS 缺陷校正的谱半径(ω = 1)一阶无限制器线性光滑限制器10102​103​104​105​101001000Ncond1​(A)NN²条件数 ‖A‖1​ ‖A−1​‖1​一阶无限制器线性光滑限制器
图 27 · 左:GS 缺陷校正的误差传播矩阵 E=I−BAIIE=I-BA_{\rm II} 的谱半径(ω=1\omega=1,默认设计的收敛解;一阶由 Jacobi 特征值 μk2\mu_k^2 精确算出,其余由 QR 算法)。三种重构的 ρ\rho 都随 NN 趋于 1。右:cond⁡1(A)\operatorname{cond}_1(A);虚线是正比于 NN 与 N2N^2 的参考线。
Figure 27 · Left: the spectral radius of the error propagator E=I-BA_II of GS defect correction (ω=1, converged solution of the default design; exact from the Jacobi eigenvalues μ_k^2 at first order, by the QR algorithm otherwise). For all three reconstructions ρ tends to 1 with N. Right: cond_1(A); the dashed lines are reference lines ∝ N and ∝ N^2.0.50.60.70.80.9110100Nρ(E)spectral radius of GS defect correction (ω = 1)first orderunlimited linearsmooth limiter10102​103​104​105​101001000Ncond1​(A)NN²condition number ‖A‖1​ ‖A−1​‖1​first orderunlimited linearsmooth limiter
Figure 27 · Left: the spectral radius of the error propagator E=I−BAIIE=I-BA_{\rm II} of GS defect correction (ω=1\omega=1, converged solution of the default design; exact from the Jacobi eigenvalues μk2\mu_k^2 at first order, by the QR algorithm otherwise). For all three reconstructions ρ\rho tends to 1 with NN. Right: cond⁡1(A)\operatorname{cond}_1(A); the dashed lines are reference lines ∝N\propto N and ∝N2\propto N^2.

下面的播放器在一个真实的线性方程组上逐行执行 GS,方程组是第一个 Newton 修正方程 AII(𝐔0) Δ𝐔I=−RI(𝐔0)A_{\rm II}(\mathbf U^0)\,\Delta\mathbf U_{\rm I}=-R_{\rm I}(\mathbf U^0)(𝐔0\mathbf U^0 是 Newton 初值):每一步更新一个内部节点,显示用到的数、新值、缺陷和与 LU 精确解的误差。

The player executes GS row by row on a real linear system, the first Newton correction system AII(𝐔0) Δ𝐔I=−RI(𝐔0)A_{\rm II}(\mathbf U^0)\,\Delta\mathbf U_{\rm I}=-R_{\rm I}(\mathbf U^0) (𝐔0\mathbf U^0 the Newton initial guess): each step updates one interior node and shows the numbers used, the new value, the defect and the error against the exact LU solution.

图 28 · GS 缺陷校正在第一个 Newton 修正方程上的缺陷 ‖b-Ax^m‖_∞ 随外迭代次数(ω=1,初值 x=0),N=8,32,128 各一个图(灰:一阶,蓝:无限制器线性;注意横轴范围不同)。降到 10^(-12) 所需的扫描次数:一阶 68、189、779,无限制器线性 53、111、553(光滑限制器 71、110、700)。直线部分的斜率是 log_10ρ(E);N=128 时缺陷先快速下降,再几乎停滞(一阶约 161 次扫描、无限制器线性约 78 次,期间每 50 次扫描下降不到 2 倍),然后才以那个速率下降(暂态)。10-12​10-9​10-6​10-3​10204060m‖b − A xm​‖∞N = 8一阶无限制器线性10-12​10-9​10-6​10-3​1050100150mN = 3210-12​10-9​10-6​10-3​10200400600mN = 128
图 28 · GS 缺陷校正在第一个 Newton 修正方程上的缺陷 ∥b−Axm∥∞\|b-Ax^m\|_\infty 随外迭代次数(ω=1\omega=1,初值 x=0x=0),N=8,32,128N=8,32,128 各一个图(灰:一阶,蓝:无限制器线性;注意横轴范围不同)。降到 10−1210^{-12} 所需的扫描次数:一阶 68、189、779,无限制器线性 53、111、553(光滑限制器 71、110、700)。直线部分的斜率是 log⁡10ρ(E)\log_{10}\rho(E);N=128N=128 时缺陷先快速下降,再几乎停滞(一阶约 161 次扫描、无限制器线性约 78 次,期间每 50 次扫描下降不到 2 倍),然后才以那个速率下降(暂态)。
Figure 28 · GS defect correction on the first Newton correction system (ω=1, initial guess x=0): the defect ‖b-Ax^m‖_∞ against the outer iteration, one panel each for N=8,32,128 (grey first order, blue unlimited linear; note the different horizontal ranges). Sweeps needed to reach 10^(-12): 68, 189, 779 at first order and 53, 111, 553 for unlimited linear (smooth limiter 71, 110, 700). The slope of the straight part is log_10ρ(E); at N=128 the defect first falls quickly, then nearly stalls (for about 161 sweeps at first order and 78 for unlimited linear it falls by less than a factor 2 per 50 sweeps) before it falls at that rate (a transient).10-12​10-9​10-6​10-3​10204060m‖b − A xm​‖∞N = 8first orderunlimited linear10-12​10-9​10-6​10-3​1050100150mN = 3210-12​10-9​10-6​10-3​10200400600mN = 128
Figure 28 · GS defect correction on the first Newton correction system (ω=1\omega=1, initial guess x=0x=0): the defect ∥b−Axm∥∞\|b-Ax^m\|_\infty against the outer iteration, one panel each for N=8,32,128N=8,32,128 (grey first order, blue unlimited linear; note the different horizontal ranges). Sweeps needed to reach 10−1210^{-12}: 68, 189, 779 at first order and 53, 111, 553 for unlimited linear (smooth limiter 71, 110, 700). The slope of the straight part is log⁡10ρ(E)\log_{10}\rho(E); at N=128N=128 the defect first falls quickly, then nearly stalls (for about 161 sweeps at first order and 78 for unlimited linear it falls by less than a factor 2 per 50 sweeps) before it falls at that rate (a transient).

最后一个面板把迭代跑到底:选 ω\omega,看缺陷的历史,测量渐近收敛因子,并与 EE 的全部特征值(复平面上的点)比较;它还画出最慢的误差模态。一阶时这个模态在出口 x=1x=1 之前的最后几个节点(N=32N=32 时最大元素在内部节点 28,节点编号 1,…,311,\dots,31)。这个位置属于 PP,而不是扫描方向:PP 是对流占优的(∣Aj,j−1∣>∣Aj,j+1∣|A_{j,j-1}|>|A_{j,j+1}|;N=32N=32 时 ∣Aj,j−1/Aj,j+1∣\sqrt{|A_{j,j-1}/A_{j,j+1}|} 在 1.37 与 1.63 之间),慢模态向下游增长。后向 GS 扫描(从 x=1x=1 扫到 x=0x=0)的谱半径相同(两者的谱都由 μk2\mu_k^2 与零组成;N=32,128N=32,128 的计算值之差不超过 10−1010^{-10},那是舍入误差),它的最慢模态也在出口附近(N=32N=32 时在节点 30);顺着流动方向扫只是缩短暂态(N=128N=128 时 779 次对 872 次)。第 17 节在切线与伴随方程上比较 GS、GMRES(以 BB 为预处理)和 LU。

The last panel runs the iteration to the end: choose ω\omega, watch the history of the defect, measure the asymptotic convergence factor and compare it with all eigenvalues of EE (points in the complex plane); it also draws the slowest error mode. At first order this mode sits in the last nodes before the outlet end x=1x=1 (at N=32N=32 its largest entry is at interior node 28 of 1,…,311,\dots,31). The location belongs to PP, not to the sweep: PP is convection-dominated (∣Aj,j−1∣>∣Aj,j+1∣|A_{j,j-1}|>|A_{j,j+1}|; at N=32N=32, ∣Aj,j−1/Aj,j+1∣\sqrt{|A_{j,j-1}/A_{j,j+1}|} lies between 1.37 and 1.63), so its slow modes grow downstream. A backward GS sweep (from x=1x=1 to x=0x=0) has the same spectral radius (both spectra consist of the squares μk2\mu_k^2 and zeros; the computed spectral radii differ by at most 10−1010^{-10} at N=32,128N=32,128, which is rounding) and its slowest mode also sits at the outlet (node 30 at N=32N=32); sweeping with the flow only shortens the transient (779 against 872 sweeps at N=128N=128). Section 17 compares GS, GMRES (with BB as the preconditioner) and LU on the tangent and adjoint systems.

第 7 节Section 7

目标函数:一个线性泛函

The objective: a linear functional

本节实验:Jh(𝐮∗)J_h(\mathbf u^*) 用的是精确节点值和梯形权重。它等于 J∗J^* 吗?如果不等,N=8N=8 时差多大,符号由什么决定?先预测,再看图 29。

Experiment: Jh(𝐮∗)J_h(\mathbf u^*) uses the exact nodal values and the trapezoid weights. Is it equal to J∗J^*? If not, how large is the difference at N=8N=8, and what sets its sign? Predict, then look at Figure 29.

连续问题的目标是 J(u)=∫01(1+x) u dxJ(u)=\int_0^1(1+x)\,u\,\mathrm dx(第 1 节)。本节把它变成节点值的函数,写出状态梯度 gg(伴随方程的右端项是 −g-g),并找出离散目标的误差来自哪里。与格心页不同,这里没有“精确平均”可以用:未知量是点值,目标是对 (1+x)u(1+x)u 的梯形公式,它对精确解也有一个求积误差,本节把它精确地写出来。

The objective of the continuous problem is J(u)=∫01(1+x) u dxJ(u)=\int_0^1(1+x)\,u\,\mathrm dx (Section 1). This section turns it into a function of the nodal values, writes the state gradient gg (the right-hand side of the adjoint equation is −g-g), and finds out where the error of the discrete objective comes from. Unlike on the cell-centred page there are no exact averages to use: the unknowns are point values, the objective is the trapezoid rule for (1+x)u(1+x)u, and it has a quadrature error even for the exact solution, which this section writes down exactly.

从积分到权重

From the integral to the weights

每个节点代表它的对偶控制体:UjU_j 被当作在 VjV_j 上都成立,VjV_j 的宽度 WjW_j 在内部节点是 hh,在两个边界节点是 h/2h/2;被积函数 (1+x)u(1+x)u 在节点处取值。于是

Each node stands for its dual interval: UjU_j is taken to hold over VjV_j, whose width WjW_j is hh at an interior node and h/2h/2 at the two boundary nodes, and the integrand (1+x)u(1+x)u is sampled at the node. So

Jh(𝐔)=∑j=0NwjUj=wT𝐔,wj=Wj (1+xj):w0=h2,wj=h (1+xj) (1≤j≤N−1),wN=h.J_h(\mathbf U)=\sum_{j=0}^{N}w_jU_j=w^T\mathbf U,\qquad w_j=W_j\,(1+x_j):\quad w_0=\frac h2,\quad w_j=h\,(1+x_j)\ (1\le j\le N-1),\quad w_N=h.

这正是对被积函数 (1+x)u(1+x)u 的复合梯形公式:h[12F0+F1+⋯+FN−1+12FN]h\bigl[\tfrac12F_0+F_1+\dots+F_{N-1}+\tfrac12F_N\bigr],Fj=(1+xj)ujF_j=(1+x_j)u_j;对偶宽度恰好就是梯形公式的权。JhJ_h 是线性的,它的状态梯度就是权向量本身,与状态无关;它没有对设计的显式依赖,二阶导数为零:

This is exactly the composite trapezoid rule for the integrand (1+x)u(1+x)u: h[12F0+F1+⋯+FN−1+12FN]h\bigl[\tfrac12F_0+F_1+\dots+F_{N-1}+\tfrac12F_N\bigr] with Fj=(1+xj)ujF_j=(1+x_j)u_j; the dual widths are the weights of the trapezoid rule. JhJ_h is linear, its state gradient is the weight vector itself, independent of the state; it has no explicit dependence on the design, and its second derivative is zero:

g=(∂Jh/∂𝐔)T=w,∂Jh∂D=0,∂2Jh∂𝐔2=0.g=(\partial J_h/\partial\mathbf U)^T=w,\qquad\frac{\partial J_h}{\partial D}=0,\qquad\frac{\partial^2J_h}{\partial\mathbf U^2}=0.

所以伴随方程 ATψ=−gA^T\psi=-g 的右端项 −g=−w-g=-w 在每个状态和设计下都一样,变的只有 ATA^T;JhJ_h 对设计的导数只通过状态:dJh/dD=wT d𝐔/dD\mathrm dJ_h/\mathrm dD=w^T\,\mathrm d\mathbf U/\mathrm dD,包括边界节点:它们以 w0,wNw_0,w_N 进入 JhJ_h,值 U0=uin(D)U_0=u_{\rm in}(D)、UN=uout(D)U_N=u_{\rm out}(D) 又随设计变化。N=8N=8 时权重在内部从 w1=0.140625w_1=0.140625 线性增长到 wN−1=0.234375w_{N-1}=0.234375,而两个端权是半个区间:w0=0.062500w_0=0.062500,wN=0.125000w_N=0.125000(格心页的权单调增长,这里端权不单调)。权之和是积分 ∫01(1+x) dx=32\int_0^1(1+x)\,\mathrm dx=\tfrac32:∑jwj=1.500000000000\sum_jw_j=1.500000000000。

So the right-hand side −g=−w-g=-w of the adjoint equation ATψ=−gA^T\psi=-g is the same at every state and every design; only ATA^T changes. The derivative of JhJ_h with respect to the design goes through the state only, dJh/dD=wT d𝐔/dD\mathrm dJ_h/\mathrm dD=w^T\,\mathrm d\mathbf U/\mathrm dD, the boundary nodes included: they enter JhJ_h with w0,wNw_0,w_N, and their values U0=uin(D)U_0=u_{\rm in}(D), UN=uout(D)U_N=u_{\rm out}(D) change with the design. At N=8N=8 the weights grow linearly in the interior from w1=0.140625w_1=0.140625 to wN−1=0.234375w_{N-1}=0.234375, while the two end weights are half intervals: w0=0.062500w_0=0.062500 and wN=0.125000w_N=0.125000 (on the cell-centred page the weights grow monotonically, here the end weights do not). The weights add up to the integral ∫01(1+x) dx=32\int_0^1(1+x)\,\mathrm dx=\tfrac32: ∑jwj=1.500000000000\sum_jw_j=1.500000000000.

权重规则是精确的吗?

Is the weight rule exact?

格心页里 Jh(⟨u∗⟩)=J∗J_h(\langle u^*\rangle)=J^* 精确成立:NN 个 NN 次单位根之和为零。这个论证在这里不适用:被积函数 F=(1+x)u∗F=(1+x)u^* 不是周期的(F(1)=2u∗(0)≠F(0)=u∗(0)F(1)=2u^*(0)\ne F(0)=u^*(0)),梯形公式不再对它精确。要精确地写出误差,用同一个工具(单位根)做完整的计算。u∗=1+a sin⁡2π(x−φ)u^*=1+a\,\sin2\pi(x-\varphi) 里的常数 11 乘以 1+x1+x 是线性函数,梯形公式对它精确,贡献 32\tfrac32。正弦部分写成 a Im⁡[e−2πiφeijθ]a\,\operatorname{Im}\bigl[e^{-2\pi\mathrm i\varphi}e^{\mathrm ij\theta}\bigr],θ=2πh\theta=2\pi h,所以 Nθ=2πN\theta=2\pi(eijθe^{\mathrm ij\theta} 就是 NN 次单位根;字母 ω\omega 留给第 6 节的松弛因子)。单位根和与它的“一阶矩”(带半权的和,xj=jhx_j=jh,hN=1hN=1)是

On the cell-centred page Jh(⟨u∗⟩)=J∗J_h(\langle u^*\rangle)=J^* holds exactly: the NN NN-th roots of unity add up to zero. That argument does not apply here: the integrand F=(1+x)u∗F=(1+x)u^* is not periodic (F(1)=2u∗(0)≠F(0)=u∗(0)F(1)=2u^*(0)\ne F(0)=u^*(0)), and the trapezoid rule is no longer exact for it. To write the error exactly, do the whole calculation with the same tool, the roots of unity. In u∗=1+a sin⁡2π(x−φ)u^*=1+a\,\sin2\pi(x-\varphi) the constant 11 times 1+x1+x is a linear function, for which the trapezoid rule is exact and contributes 32\tfrac32. The sine part is a Im⁡[e−2πiφeijθ]a\,\operatorname{Im}\bigl[e^{-2\pi\mathrm i\varphi}e^{\mathrm ij\theta}\bigr] with θ=2πh\theta=2\pi h, so Nθ=2πN\theta=2\pi (the numbers eijθe^{\mathrm ij\theta} are the NN-th roots of unity; the letter ω\omega is kept for the relaxation factor of Section 6). The sum of the roots of unity and its “first moment” (sums with half weights at both ends, xj=jhx_j=jh, hN=1hN=1) are

∑′j=0Neijθ=0,∑′j=0Nj eijθ=N2 eiθ+1eiθ−1=−iN2cot⁡(πh)≠0,\mathop{{\sum}'}_{j=0}^{N}e^{\mathrm ij\theta}=0,\qquad\mathop{{\sum}'}_{j=0}^{N}j\,e^{\mathrm ij\theta}=\frac N2\,\frac{e^{\mathrm i\theta}+1}{e^{\mathrm i\theta}-1}=-\frac{\mathrm iN}2\cot(\pi h)\ne0,

其中带撇的和表示两端取半权。第一个和与格心页的“零”是同一件事;第二个和不为零,正是它留下了误差:梯形和的正弦部分与精确积分是

where the primed sums have half weights at both ends. The first sum is the same “zero” as on the cell-centred page; the second does not vanish, and it is what leaves the error: the sine part of the trapezoid sum and the exact integral are

h∑′j=0N(1+xj) a Im⁡[e−2πiφeijθ]=−a h2cot⁡(πh)cos⁡2πφ,∫01(1+x) asin⁡2π(x−φ) dx=−a cos⁡2πφ2π.h\mathop{{\sum}'}_{j=0}^{N}(1+x_j)\,a\,\operatorname{Im}\bigl[e^{-2\pi\mathrm i\varphi}e^{\mathrm ij\theta}\bigr]=-\frac{a\,h}2\cot(\pi h)\cos2\pi\varphi,\qquad\int_0^1(1+x)\,a\sin2\pi(x-\varphi)\,\mathrm dx=-\frac{a\,\cos2\pi\varphi}{2\pi}.

两式相减:

Subtracting:

Jh(𝐮∗)−J∗=a cos⁡2πφ2π(1−πhcot⁡πh)对每个 N≥2 都成立(精确)。J_h(\mathbf u^*)-J^*=\frac{a\,\cos2\pi\varphi}{2\pi}\bigl(1-\pi h\cot\pi h\bigr)\qquad\text{对每个 }N\ge2\text{ 都成立(精确)。}
Jh(𝐮∗)−J∗=a cos⁡2πφ2π(1−πhcot⁡πh)for every N≥2 (exact).J_h(\mathbf u^*)-J^*=\frac{a\,\cos2\pi\varphi}{2\pi}\bigl(1-\pi h\cot\pi h\bigr)\qquad\text{for every }N\ge2\ \text{(exact).}

展开 1−πhcot⁡πh=(πh)23+(πh)445+2(πh)6945+⋯1-\pi h\cot\pi h=\tfrac{(\pi h)^2}3+\tfrac{(\pi h)^4}{45}+\tfrac{2(\pi h)^6}{945}+\cdots,得到

Expanding 1−πhcot⁡πh=(πh)23+(πh)445+2(πh)6945+⋯1-\pi h\cot\pi h=\tfrac{(\pi h)^2}3+\tfrac{(\pi h)^4}{45}+\tfrac{2(\pi h)^6}{945}+\cdots gives

Jh(𝐮∗)−J∗=h212 u∗′(0)−h4720 u∗′′′(0)+h630240 u∗(5)(0)−⋯ ,u∗′(0)=2πa cos⁡2πφ.J_h(\mathbf u^*)-J^*=\frac{h^2}{12}\,u^{*\prime}(0)-\frac{h^4}{720}\,u^{*\prime\prime\prime}(0)+\frac{h^6}{30240}\,u^{*(5)}(0)-\cdots,\qquad u^{*\prime}(0)=2\pi a\,\cos2\pi\varphi.

这就是 Euler–Maclaurin 公式:误差由被积函数 F=(1+x)u∗F=(1+x)u^* 的奇数阶导数在两端的跳跃决定,而 u∗u^* 是周期的,所以这些跳跃就是 u∗(2k−1)(0)u^{*(2k-1)}(0)。求积误差不会消失:对每个 NN,Jh(𝐮∗)≠J∗J_h(\mathbf u^*)\ne J^*,它按 h2h^2 趋于零,系数是 π6a cos⁡2πφ=0.094753\tfrac{\pi}{6}a\,\cos2\pi\varphi=0.094753;默认设计里 u∗′(0)>0u^{*\prime}(0)>0,所以梯形公式偏大。N=8N=8:Jh(𝐮∗)−J∗=0.00149597J_h(\mathbf u^*)-J^*=0.00149597(模型的精确节点值,求和得到),封闭公式给出 0.00149597(两者之差小于 10−1510^{-15},是舍入);展开的三项是 0.00148052、0.00001522、0.00000022,前两项之和 0.00149574 的余项 2.3e−7 就是第三项 2.2e−7 的量级。把封闭公式与直接的梯形求和比较:N=8N=8 到 4096 的差别(相对)不超过 5×10−65\times10^{-6}(最大的差别出现在最细的网格:那里求积误差最小,求和的舍入相对最重);对 sin⁡2πm(x−φ)\sin2\pi m(x-\varphi)(m=1,2,3m=1,2,3,N=8,16,32N=8,16,32)同样的推导给出 cos⁡2πmφ2πm(1−πmhcot⁡πmh)\tfrac{\cos2\pi m\varphi}{2\pi m}(1-\pi mh\cot\pi mh),与直接求和之差不超过 5×10−155\times10^{-15}。

This is the Euler–Maclaurin formula: the error is set by the jumps of the odd derivatives of the integrand F=(1+x)u∗F=(1+x)u^* between the two ends, and since u∗u^* is periodic the jumps are u∗(2k−1)(0)u^{*(2k-1)}(0). The quadrature error does not go away: for every NN, Jh(𝐮∗)≠J∗J_h(\mathbf u^*)\ne J^*, and it tends to zero like h2h^2 with the coefficient π6a cos⁡2πφ=0.094753\tfrac{\pi}{6}a\,\cos2\pi\varphi=0.094753; at the default design u∗′(0)>0u^{*\prime}(0)>0, so the trapezoid rule overestimates. At N=8N=8: Jh(𝐮∗)−J∗=0.00149597J_h(\mathbf u^*)-J^*=0.00149597 (the model's exact nodal values, summed), the closed form gives 0.00149597 (they differ by less than 10−1510^{-15}, which is rounding); the three terms of the expansion are 0.00148052, 0.00001522 and 0.00000022, and the remainder 2.3e−7 after the first two, 0.00149574 together, is of the size of the third term 2.2e−7. Against the direct trapezoid sum the closed form differs (relatively) by at most 5×10−65\times10^{-6} for N=8N=8 to 4096 (the largest difference is at the finest mesh, where the quadrature error is smallest and the rounding of the sum weighs most); for sin⁡2πm(x−φ)\sin2\pi m(x-\varphi) (m=1,2,3m=1,2,3, N=8,16,32N=8,16,32) the same derivation gives cos⁡2πmφ2πm(1−πmhcot⁡πmh)\tfrac{\cos2\pi m\varphi}{2\pi m}(1-\pi mh\cot\pi mh), which differs from the direct sum by at most 5×10−155\times10^{-15}.

图 29 · 求积误差的 Euler–Maclaurin 结构(默认设计,由封闭公式算出,所以余项不受舍入误差限制)。蓝:|J_h(u*)-J*|,按 h^2 下降;紫:减去第一项 (h^2)/12u*′(0) 之后的余项,按 h^4 下降;绿:再减去第二项之后,按 h^6 下降;橙:再减去第三项之后。虚线是 h^2,h^4,h^6 的参考斜率。格心页的同一个量恒为零(舍入误差),这里是一个明确的、按 h^2 下降的数。10-18​10-15​10-12​10-9​10-6​10-3​110100N|梯形公式误差| 与余项h²h⁴h⁶Jh​(u*) − J*减去 (h²/12)u*′(0) 之后再减去 −(h⁴/720)u*‴(0)再减去第三项
图 29 · 求积误差的 Euler–Maclaurin 结构(默认设计,由封闭公式算出,所以余项不受舍入误差限制)。蓝:∣Jh(𝐮∗)−J∗∣|J_h(\mathbf u^*)-J^*|,按 h2h^2 下降;紫:减去第一项 h212u∗′(0)\tfrac{h^2}{12}u^{*\prime}(0) 之后的余项,按 h4h^4 下降;绿:再减去第二项之后,按 h6h^6 下降;橙:再减去第三项之后。虚线是 h2,h4,h6h^2,h^4,h^6 的参考斜率。格心页的同一个量恒为零(舍入误差),这里是一个明确的、按 h2h^2 下降的数。
Figure 29 · The Euler–Maclaurin structure of the quadrature error (default design, computed from the closed form, so the remainders are not limited by rounding). Blue: |J_h(u*)-J*|, falling like h^2; violet: the remainder after the first term (h^2)/12u*′(0), falling like h^4; green: after the second term as well, falling like h^6; orange: after the third. Dashed lines are the reference slopes h^2,h^4,h^6. On the cell-centred page the same quantity is zero (rounding); here it is a definite number that falls like h^2.10-18​10-15​10-12​10-9​10-6​10-3​110100N|trapezoid error| and remaindersh²h⁴h⁶Jh​(u*) − J*after (h²/12)u*′(0)and −(h⁴/720)u*‴(0)and the third term
Figure 29 · The Euler–Maclaurin structure of the quadrature error (default design, computed from the closed form, so the remainders are not limited by rounding). Blue: ∣Jh(𝐮∗)−J∗∣|J_h(\mathbf u^*)-J^*|, falling like h2h^2; violet: the remainder after the first term h212u∗′(0)\tfrac{h^2}{12}u^{*\prime}(0), falling like h4h^4; green: after the second term as well, falling like h6h^6; orange: after the third. Dashed lines are the reference slopes h2,h4,h6h^2,h^4,h^6. On the cell-centred page the same quantity is zero (rounding); here it is a definite number that falls like h2h^2.

同一个误差也出现在梯度里。Jh(𝐮∗(D))−J∗(D)J_h(\mathbf u^*(D))-J^*(D) 对设计的导数就是封闭公式对 a,φa,\varphi 的导数:(cos⁡2πφ2π, −a sin⁡2πφ, 0) (1−πhcot⁡πh)\bigl(\tfrac{\cos2\pi\varphi}{2\pi},\,-a\,\sin2\pi\varphi,\,0\bigr)\,(1-\pi h\cot\pi h),N=8N=8 时是 (0.007480, −0.004423, 0)(0.007480,\ −0.004423,\ 0),对模型的中心差分(τ=10−6\tau=10^{-6})给出 (0.007480, −0.004423, 0.000000)(0.007480,\ −0.004423,\ 0.000000)。即使把精确节点值代入,离散目标的梯度也与连续梯度相差 O(h2)O(h^2);离散伴随算的是 JhJ_h 的导数,第 15、16 节把这一项和状态误差对梯度的影响分开。

The same error shows up in the gradient. The derivative of Jh(𝐮∗(D))−J∗(D)J_h(\mathbf u^*(D))-J^*(D) with respect to the design is the derivative of the closed form with respect to a,φa,\varphi: (cos⁡2πφ2π, −a sin⁡2πφ, 0) (1−πhcot⁡πh)\bigl(\tfrac{\cos2\pi\varphi}{2\pi},\,-a\,\sin2\pi\varphi,\,0\bigr)\,(1-\pi h\cot\pi h), which at N=8N=8 is (0.007480, −0.004423, 0)(0.007480,\ −0.004423,\ 0), and central differences of the model (τ=10−6\tau=10^{-6}) give (0.007480, −0.004423, 0.000000)(0.007480,\ −0.004423,\ 0.000000). Even with the exact nodal values put in, the gradient of the discrete objective differs from the continuous gradient by O(h2)O(h^2); the discrete adjoint computes the derivative of JhJ_h, and Sections 15 and 16 separate this term from the effect of the state error on the gradient.

下面的面板自己试:选被积函数里的谐波数 mm、权函数(1+x1+x 或 11)、NN 与 φ\varphi,看梯形和、精确积分、误差与封闭公式。权函数取 11 时被积函数是周期的,误差为零(m<Nm<N):这就是格心页的情形。

Try it yourself in the panel below: choose the harmonic number mm in the integrand, the weight function (1+x1+x or 11), NN and φ\varphi, and see the trapezoid sum, the exact integral, the error and the closed form. With the weight 11 the integrand is periodic and the error vanishes (m<Nm<N): that is the situation of the cell-centred page.

JhJ_h 的误差:状态误差加求积误差

The error of JhJ_h: state error plus quadrature error

因为 JhJ_h 对 𝐔\mathbf U 是线性的,它的误差可以精确地分成两部分:

Because JhJ_h is linear in 𝐔\mathbf U, its error splits exactly into two parts:

Jh(𝐔)−J∗=wT(𝐔−𝐮∗)⏟状态部分+Jh(𝐮∗)−J∗⏟求积部分.J_h(\mathbf U)-J^*=\underbrace{w^T\bigl(\mathbf U-\mathbf u^*\bigr)}_{\text{状态部分}}+\underbrace{J_h(\mathbf u^*)-J^*}_{\text{求积部分}}.
Jh(𝐔)−J∗=wT(𝐔−𝐮∗)⏟state part+Jh(𝐮∗)−J∗⏟quadrature part.J_h(\mathbf U)-J^*=\underbrace{w^T\bigl(\mathbf U-\mathbf u^*\bigr)}_{\text{state part}}+\underbrace{J_h(\mathbf u^*)-J^*}_{\text{quadrature part}}.

权都是正的,所以状态部分不超过 ∑jwj ∥𝐔−𝐮∗∥∞=32∥𝐔−𝐮∗∥∞\sum_jw_j\,\|\mathbf U-\mathbf u^*\|_\infty=\tfrac32\|\mathbf U-\mathbf u^*\|_\infty;实测 ∣wT(𝐔−𝐮∗)∣/∥𝐔−𝐮∗∥∞|w^T(\mathbf U-\mathbf u^*)|/\|\mathbf U-\mathbf u^*\|_\infty 在 N=8N=8 到 4096 的最大值:一阶 0.745,无限制器线性 0.546,光滑限制器 0.740,都不超过 32\tfrac32(正负误差相互抵消,所以通常远小于它)。默认设计 N=8N=8:J∗=1.471198J^*=1.471198,JhJ_h 是 1.280916(一阶)、1.463945(无限制器线性)和 1.462683(光滑限制器);无限制器线性的 Jh−J∗=−0.007254J_h-J^*=−0.007254,其中状态部分 −0.008749,求积部分 0.001496。

The weights are all positive, so the state part is at most ∑jwj ∥𝐔−𝐮∗∥∞=32∥𝐔−𝐮∗∥∞\sum_jw_j\,\|\mathbf U-\mathbf u^*\|_\infty=\tfrac32\|\mathbf U-\mathbf u^*\|_\infty; measured, the largest ∣wT(𝐔−𝐮∗)∣/∥𝐔−𝐮∗∥∞|w^T(\mathbf U-\mathbf u^*)|/\|\mathbf U-\mathbf u^*\|_\infty for N=8N=8 to 4096 is 0.745 at first order, 0.546 for unlimited linear and 0.740 for the smooth limiter, none above 32\tfrac32 (errors of both signs cancel, so it is usually far below). At the defaults (N=8N=8) J∗=1.471198J^*=1.471198 and JhJ_h is 1.280916 (first order), 1.463945 (unlimited linear) and 1.462683 (smooth limiter); for unlimited linear Jh−J∗=−0.007254J_h-J^*=−0.007254, made of the state part −0.008749 and the quadrature part 0.001496.

图 30 · 目标是由什么组成的(默认设计,N=8,无限制器线性)。左:权重 w_j=W_j(1+x_j)(紫;两个端权是半个区间)与每个节点的贡献 w_jU_j(蓝)。右:贡献的部分和;最后一点是 J_h=1.463945,虚线是 J*=1.471198。00.050.10.150.20.2500.20.40.60.81xj​权重与贡献gj​ = wj​ = Wj​(1 + xj​)wj​ Uj​00.20.40.60.811.21.41.600.20.40.60.81xj​J* = 1.471198Jh​ = 1.463945部分和 Σk≤j​ wk​ Uk​
图 30 · 目标是由什么组成的(默认设计,N=8N=8,无限制器线性)。左:权重 wj=Wj(1+xj)w_j=W_j(1+x_j)(紫;两个端权是半个区间)与每个节点的贡献 wjUjw_jU_j(蓝)。右:贡献的部分和;最后一点是 Jh=1.463945J_h=1.463945,虚线是 J∗=1.471198J^*=1.471198。
Figure 30 · What the objective is made of (default design, N=8, unlimited linear). Left: the weights w_j=W_j(1+x_j) (violet; the two end weights are half intervals) and the contribution w_jU_j of every node (blue). Right: the partial sums of the contributions; the last point is J_h=1.463945, the dashed line J*=1.471198.00.050.10.150.20.2500.20.40.60.81xj​weights and contributionsgj​ = wj​ = Wj​(1 + xj​)wj​ Uj​00.20.40.60.811.21.41.600.20.40.60.81xj​J* = 1.471198Jh​ = 1.463945partial sums Σk≤j​ wk​ Uk​
Figure 30 · What the objective is made of (default design, N=8N=8, unlimited linear). Left: the weights wj=Wj(1+xj)w_j=W_j(1+x_j) (violet; the two end weights are half intervals) and the contribution wjUjw_jU_j of every node (blue). Right: the partial sums of the contributions; the last point is Jh=1.463945J_h=1.463945, the dashed line J∗=1.471198J^*=1.471198.

下面的面板对当前设计和当前解做这个分解:权重、贡献、两部分误差,以及每个节点对状态部分的贡献。

The panel below makes this decomposition for the current design and the current solution: the weights, the contributions, the two parts of the error and what every node contributes to the state part.

加密。两部分都是 O(h2)O(h^2)(二阶重构),而且符号相反时会部分抵消。默认设计、无限制器线性:N=4096N=4096 时 Jh−J∗=−1.253×10−8J_h-J^*=-1.253\times10^{-8},状态部分是 −1.818e−8,求积部分是 5.648e−9(除以 h2h^2:−0.2102、−0.3050、0.0948,最后一个就是极限 0.0948)。状态部分变号 2 次(N=8N=8 与 N=16N=16 之间、N=256N=256 与 N=512N=512 之间),Jh−J∗J_h-J^* 变号 2 次(N=8N=8 与 N=16N=16 之间、N=512N=512 与 N=1024N=1024 之间),所以相邻两次加密的观测阶很不规则(1.36、1.40、2.16、2.63、3.17、4.83、0.67、1.20、1.72;最后一次 1.72),N=4096N=4096 附近还没有进入渐近区。一阶:状态部分占优,观测阶 1.00;光滑限制器 0.97(第 4 节说明光滑限制器为什么在细网格上降为一阶)。独立 Python 程序(python/solve_node.py)存的 JhJ_h 与本页相差不超过 2×10−132\times10^{-13}(三种重构,N=32N=32 到 4096),它的 objective_quadrature_error 与封闭公式相差不超过 2×10−142\times10^{-14}。

Refinement. Both parts are O(h2)O(h^2) (second-order reconstruction), and they partly cancel when their signs are opposite. Default design, unlimited linear: at N=4096N=4096, Jh−J∗=−1.253×10−8J_h-J^*=-1.253\times10^{-8}, the state part is −1.818e−8 and the quadrature part 5.648e−9 (divided by h2h^2: −0.2102, −0.3050, 0.0948, the last being the limit 0.0948). The state part changes sign twice (between N=8N=8 and N=16N=16, between N=256N=256 and N=512N=512) and Jh−J∗J_h-J^* twice (between N=8N=8 and N=16N=16, between N=512N=512 and N=1024N=1024), so the observed orders of consecutive doublings are irregular (1.36, 1.40, 2.16, 2.63, 3.17, 4.83, 0.67, 1.20, 1.72; 1.72 for the last) and the asymptotic range is not reached near N=4096N=4096. At first order the state part dominates, with observed order 1.00; the smooth limiter gives 0.97 (Section 4 explains why it drops to first order on fine meshes). The JhJ_h stored by the independent Python program (python/solve_node.py) differs from this page's by at most 2×10−132\times10^{-13} (three reconstructions, N=32N=32 to 4096), and its objective_quadrature_error differs from the closed form by at most 2×10−142\times10^{-14}.

NNJh−J∗J_h-J^*wT(𝐔−𝐮∗)w^T(\mathbf U-\mathbf u^*)Jh(𝐮∗)−J∗J_h(\mathbf u^*)-J^*(Jh−J∗)/h2(J_h-J^*)/h^2
8−7.25e−3−8.75e−31.50e−3−0.4642
321.07e−39.77e−49.26e−51.0953
1283.86e−53.28e−55.78e−60.6317
5121.51e−7−2.10e−73.61e−70.0396
2048−4.12e−8−6.37e−82.26e−8−0.1726
4096−1.25e−8−1.82e−85.65e−9−0.2102
图 31 · |J_h(U)-J*| 随 N(默认设计,N=8 到 4096)。三种重构;方块是求积部分 |J_h(u*)-J*|,按 h^2 下降。无限制器线性的曲线在 N=8 与 N=16 之间、N=512 与 N=1024 之间穿过零(对数轴上的深谷,两个相反的 O(h^2) 项相互抵消)。虚线是 h 与 h^2 的参考斜率。10-9​10-7​10-5​10-3​10-1​101001000N|Jh​ − J*|hh²Jh​(U) − J*,一阶Jh​(U) − J*,无限制器线性Jh​(U) − J*,光滑限制器Jh​(u*) − J*(求积误差)
图 31 · ∣Jh(𝐔)−J∗∣|J_h(\mathbf U)-J^*| 随 NN(默认设计,N=8N=8 到 4096)。三种重构;方块是求积部分 ∣Jh(𝐮∗)−J∗∣|J_h(\mathbf u^*)-J^*|,按 h2h^2 下降。无限制器线性的曲线在 N=8N=8 与 N=16N=16 之间、N=512N=512 与 N=1024N=1024 之间穿过零(对数轴上的深谷,两个相反的 O(h2)O(h^2) 项相互抵消)。虚线是 hh 与 h2h^2 的参考斜率。
Figure 31 · |J_h(U)-J*| against N (default design, N=8 to 4096). The three reconstructions; the squares are the quadrature part |J_h(u*)-J*|, falling like h^2. The curve of unlimited linear passes through zero between N=8 and N=16 and between N=512 and N=1024 (a deep valley on the logarithmic axis: two opposite O(h^2) terms cancel). Dashed lines are the reference slopes h and h^2.10-9​10-7​10-5​10-3​10-1​101001000N|Jh​ − J*|hh²Jh​(U) − J*, first orderJh​(U) − J*, unlimited linearJh​(U) − J*, smooth limiterJh​(u*) − J* (quadrature error)
Figure 31 · ∣Jh(𝐔)−J∗∣|J_h(\mathbf U)-J^*| against NN (default design, N=8N=8 to 4096). The three reconstructions; the squares are the quadrature part ∣Jh(𝐮∗)−J∗∣|J_h(\mathbf u^*)-J^*|, falling like h2h^2. The curve of unlimited linear passes through zero between N=8N=8 and N=16N=16 and between N=512N=512 and N=1024N=1024 (a deep valley on the logarithmic axis: two opposite O(h2)O(h^2) terms cancel). Dashed lines are the reference slopes hh and h2h^2.
图 32 · 无限制器线性的分解 J_h-J*=w^T(U-u*)+(J_h(u*)-J*)(默认设计):总误差(蓝)、状态部分(紫)与求积部分(橙)的绝对值,空心圈表示负值。求积部分恒为正且按 h^2 下降;状态部分在 N=8 为负,N=16 到 256 为正,N ≥ 512 又为负;两者符号相反的地方,总误差小于其中较大的一个。10-9​10-7​10-5​10-3​10-1​101001000N绝对值(空心圈:负值)hh²Jh​(U) − J*状态部分 wT​(U − u*)求积部分 Jh​(u*) − J*
图 32 · 无限制器线性的分解 Jh−J∗=wT(𝐔−𝐮∗)+(Jh(𝐮∗)−J∗)J_h-J^*=w^T(\mathbf U-\mathbf u^*)+\bigl(J_h(\mathbf u^*)-J^*\bigr)(默认设计):总误差(蓝)、状态部分(紫)与求积部分(橙)的绝对值,空心圈表示负值。求积部分恒为正且按 h2h^2 下降;状态部分在 N=8N=8 为负,N=16N=16 到 256 为正,N≥512N\ge512 又为负;两者符号相反的地方,总误差小于其中较大的一个。
Figure 32 · The decomposition J_h-J*=w^T(U-u*)+(J_h(u*)-J*) for unlimited linear (default design): absolute values of the total error (blue), the state part (violet) and the quadrature part (orange), an open ring marking a negative value. The quadrature part is always positive and falls like h^2; the state part is negative at N=8, positive for N=16 to 256 and negative from N=512 on; where their signs are opposite the total error is smaller than the larger of the two.10-9​10-7​10-5​10-3​10-1​101001000Nabsolute value (open ring: negative)hh²Jh​(U) − J*state part wT​(U − u*)quadrature part Jh​(u*) − J*
Figure 32 · The decomposition Jh−J∗=wT(𝐔−𝐮∗)+(Jh(𝐮∗)−J∗)J_h-J^*=w^T(\mathbf U-\mathbf u^*)+\bigl(J_h(\mathbf u^*)-J^*\bigr) for unlimited linear (default design): absolute values of the total error (blue), the state part (violet) and the quadrature part (orange), an open ring marking a negative value. The quadrature part is always positive and falls like h2h^2; the state part is negative at N=8N=8, positive for N=16N=16 to 256 and negative from N=512N=512 on; where their signs are opposite the total error is smaller than the larger of the two.

在浏览器里自己量一量(当前设计,N=8N=8 到 256,用带状 Newton 法求解),表里还有两部分误差:

Measure it yourself at the current design (N=8N=8 to 256, solved in the browser with the band Newton method); the table also lists the two parts of the error:

伴随方程的右端项是 −g=−w-g=-w:一个全为负的向量,内部分量的大小随 xx 线性增长,两端是半权 −w0,−wN-w_0,-w_N,与状态无关。第 9、11 节用它计算伴随 ψ\psi。

The right-hand side of the adjoint equation is −g=−w-g=-w: a negative vector whose interior entries grow in size linearly with xx, with the half weights −w0,−wN-w_0,-w_N at the two ends, and it does not depend on the state. Sections 9 and 11 use it to compute the adjoint ψ\psi.

第 8 节Section 8

前向:沿着面循环传播切向量

Forward: the tangent through the face loop

本节实验:只给一个未知量一个单位的扰动 𝐔˙=e3\dot{\mathbf U}=e_3,设计不动:残差的哪几行会变、各变多少?先用第 3 节的面模板预测,再在本节的逐列播放器里验证。

Experiment: Seed one unknown, 𝐔˙=e3\dot{\mathbf U}=e_3, and hold the design fixed: which rows of the residual change, and by how much? Predict from the face stencil of Section 3, then check with the column player of this section.

第 5–7 节写出了残差代码 R(𝐔,D)R(\mathbf U,D)(五条语句),解出了 R=0R=0,定义了目标 JhJ_h。本节用前向模式对残差代码求导:输入是未知量与设计的一个联合方向 (𝐔˙,D˙)(\dot{\mathbf U},\dot D),输出是每个残差沿这个方向的导数,全程不形成矩阵。第 9 节把同一段代码倒过来运行。

Sections 5–7 built the residual code R(𝐔,D)R(\mathbf U,D) of five statements, solved R=0R=0 and defined the objective JhJ_h. This section differentiates the residual code in forward mode: a joint direction (𝐔˙,D˙)(\dot{\mathbf U},\dot D) of the unknowns and the design goes in, the derivative of every residual along that direction comes out, and no matrix is formed. Section 9 runs the same code backwards.

矩阵乘积可以写成方向导数

A matrix product as a directional derivative

先固定设计(D˙=0\dot D=0),让所有未知量沿方向 vv 一起变化:𝐔(t)=𝐔+tv\mathbf U(t)=\mathbf U+t v。向量 vv 就是状态切向量 𝐔˙\dot{\mathbf U},它规定每个未知量随 tt 变化的快慢。对每个残差在 t=0t=0 处关于 tt 求导,得到残差切向量 R˙=Av\dot R=Av:一次矩阵向量乘积,却不需要矩阵本身。

First hold the design fixed (D˙=0\dot D=0) and move all unknowns together along a direction vv: 𝐔(t)=𝐔+tv\mathbf U(t)=\mathbf U+t v. The vector vv is the state tangent 𝐔˙\dot{\mathbf U}; it says how fast each unknown changes with tt. Differentiating each residual with respect to tt at t=0t=0 gives the residual tangent R˙=Av\dot R=Av: a matrix–vector product, computed without the matrix.

R˙i=(Av)i=ddtRi(𝐔+tv,D)∣t=0=∑j∂Ri∂Uj vj.\dot R_i=(Av)_i=\frac{\mathrm d}{\mathrm dt}R_i(\mathbf U+t v,D)\Big|_{t=0}=\sum_j\frac{\partial R_i}{\partial U_j}\,v_j.

再让设计也动起来,D(t)=D+tD˙D(t)=D+t\dot D,链式法则多出设计 Jacobian 一项。自动微分的前向(切线)模式就是这样计算的:残差代码里的每个中间量 xx 都配一个切向量 x˙\dot x,按 xx 本身的计算顺序算出。

Let the design move as well, D(t)=D+tD˙D(t)=D+t\dot D, and the chain rule adds the design Jacobian. The forward (tangent) mode of automatic differentiation computes exactly this: every intermediate xx of the residual code gets a tangent x˙\dot x, computed in the same order as xx itself.

R˙=ddtR(𝐔+t𝐔˙, D+tD˙)∣t=0=A 𝐔˙+RD D˙.\dot R=\frac{\mathrm d}{\mathrm dt}R\big(\mathbf U+t\dot{\mathbf U},\,D+t\dot D\big)\Big|_{t=0}=A\,\dot{\mathbf U}+R_D\,\dot D.

记号:上点 x˙\dot x 与上横线 xˉ\bar x 是离散程序的前向导数与反向(伴随)导数。代码沿用 Tapenade 等自动微分工具的命名:前向子程序 residual_d 读入种子 u_d ≡𝐔˙\equiv\dot{\mathbf U}、D_d ≡D˙\equiv\dot D,返回 res_d ≡R˙\equiv\dot R;第 9 节的 residual_b 读入 res_b ≡Rˉ\equiv\bar R,返回 u_b ≡𝐔ˉ\equiv\bar{\mathbf U} 与 D_b ≡Dˉ\equiv\bar D。

Notation: the dot x˙\dot x and the bar xˉ\bar x are the forward and the reverse (adjoint) derivatives of the discrete program. The code uses the names of AD tools such as Tapenade: the forward routine residual_d takes the seeds u_d ≡𝐔˙\equiv\dot{\mathbf U} and D_d ≡D˙\equiv\dot D and returns res_d ≡R˙\equiv\dot R; the residual_b of Section 9 takes res_b ≡Rˉ\equiv\bar R and returns u_b ≡𝐔ˉ\equiv\bar{\mathbf U} and D_b ≡Dˉ\equiv\bar D.

代码里的运算与它们的求导规则

The rules for the operations of the code

残差代码的每条语句都由少数几种运算搭成。下表给出每种运算的前向规则(本节)和伴随规则(第 9 节):伴随规则是前向规则的转置,用的是同一批偏导数——∂z/∂x\partial z/\partial x 在前向乘 x˙\dot x,在反向乘 zˉ\bar z。后面的语句表对每条语句用的正是这些规则,表里的“局部导数”就是这些偏导数在当前状态上的值。

Every statement of the residual code is built from a few operations. The table gives, for each, the tangent rule (this section) and the adjoint rule (Section 9): the adjoint rule is the transpose of the tangent rule and uses the same partial derivatives — ∂z/∂x\partial z/\partial x multiplies x˙\dot x going forward and zˉ\bar z going backward. The statement tables below apply exactly these rules, and the “local derivatives” of the tables are these partial derivatives at the current state.

运算Operation前向规则Tangent rule伴随规则(第 9 节)Adjoint rule (Section 9)在代码里In the code
z=x±yz=x\pm yz˙=x˙±y˙\dot z=\dot x\pm\dot yxˉ+=zˉ,  yˉ+=±zˉ\bar x\mathrel{\text{+=}}\bar z,\ \ \bar y\mathrel{\text{+=}}\pm\bar z差 lj,rjl_j,r_j;分发 Rf+=HfR_f\mathrel{\text{+=}}H_f;源项 Qj−Qj−1Q_j-Q_{j-1}the differences lj,rjl_j,r_j; the scatter Rf+=HfR_f\mathrel{\text{+=}}H_f; the source Qj−Qj−1Q_j-Q_{j-1}
z=c xz=c\,x(cc 是常数)z=c xz=c\,x (cc a constant)z˙=c x˙\dot z=c\,\dot xxˉ+=c zˉ\bar x\mathrel{\text{+=}}c\,\bar z系数 12, 14, 1/h\tfrac12,\ \tfrac14,\ 1/hthe factors 12, 14, 1/h\tfrac12,\ \tfrac14,\ 1/h
z=x yz=x\,yz˙=x˙ y+x y˙\dot z=\dot x\,y+x\,\dot yxˉ+=y zˉ,  yˉ+=x zˉ\bar x\mathrel{\text{+=}}y\,\bar z,\ \ \bar y\mathrel{\text{+=}}x\,\bar zν (UR−UL), a sin⁡z\nu\,(U_R-U_L),\ a\,\sin z
z=x2z=x^2z˙=2x x˙\dot z=2x\,\dot xxˉ+=2x zˉ\bar x\mathrel{\text{+=}}2x\,\bar zqL2, qR2, (u∗)2q_L^2,\ q_R^2,\ (u^*)^2
z=x/yz=x/yz˙=(x˙−z y˙)/y\dot z=(\dot x-z\,\dot y)/yxˉ+=zˉ/y,  yˉ+=−z zˉ/y\bar x\mathrel{\text{+=}}\bar z/y,\ \ \bar y\mathrel{\text{+=}}-z\,\bar z/y限制器 σ=l r (l+r)/(l2+r2+ϵ2)\sigma=l\,r\,(l+r)/(l^2+r^2+\epsilon^2)the limiter σ=l r (l+r)/(l2+r2+ϵ2)\sigma=l\,r\,(l+r)/(l^2+r^2+\epsilon^2)
z=sin⁡xz=\sin xz˙=cos⁡x x˙\dot z=\cos x\,\dot xxˉ+=cos⁡x zˉ\bar x\mathrel{\text{+=}}\cos x\,\bar zu∗, q∗, uinu^*,\ q^*,\ u_{\rm in} 里的 sin⁡ 2π(x−φ)\sin\,2\pi(x-\varphi)the sin⁡\sin of 2π(x−φ)2\pi(x-\varphi) in u∗, q∗, uinu^*,\ q^*,\ u_{\rm in}
z=cos⁡xz=\cos xz˙=−sin⁡x x˙\dot z=-\sin x\,\dot xxˉ+=−sin⁡x zˉ\bar x\mathrel{\text{+=}}-\sin x\,\bar zq∗q^* 里 ux∗=2πa cos⁡zu^*_x=2\pi a\,\cos z 的 cos⁡\costhe cos⁡\cos in ux∗=2πa cos⁡zu^*_x=2\pi a\,\cos z inside q∗q^*
z=ϕ(x1,…,xm)z=\phi(x_1,\dots,x_m)z˙=∑k∂kϕ x˙k\dot z=\sum_k\partial_k\phi\,\dot x_kxˉk+=∂kϕ zˉ\bar x_k\mathrel{\text{+=}}\partial_k\phi\,\bar z整条语句:通量 HH、斜率 σ\sigma、QQa whole statement: the flux HH, the slope σ\sigma, QQ

一个变量被多条语句读(扇出)时,前向什么也不用做;反向每条读它的语句各给一项,所以伴随必须用 += 累加(第 9 节的扇入)。

When a variable is read by several statements (a fan-out), nothing special happens going forward; going backward every statement that reads it contributes one term, so the adjoint must accumulate with += (the fan-in of Section 9).

图 33 · 一个面的前向数据流(面 f=3,在节点 3 与 4 之间;默认设计,无限制器线性重构;种子 U=v_0、D-dot=e_0,即第 10 节振幅 a 方向的切线解)。从左到右是程序顺序:(1)面读入 4 个未知量;(2)面两端节点上的斜率、迹 q_L,q_R、未重构状态 U_L,U_R 和黏性 ν 组成面输入 z_f(面的输入向量,不是第 1 节正弦的自变量 z=2π(x-φ));(3)通量 H_f;(4)分发到 R_3、R_4。每个方框给出原始值和(绿色的)切向量,每条箭头上是它所乘的局部导数。每个面两侧都有节点,所以所有面用同一段代码;在面 0 和面 N-1 上,被写入的两行之一是约束行,面不向它写入(第 4 节)。(1)取值(2)重构:斜率、迹、未重构状态、ν(3)通量(4)分发1111½−½cL​κf​−κf​cR​−(UR​ − UL​)/df​+1−1U2​ = 1.1708U̇2​ = 0.8569U3​ = 1.1656U̇3​ = 0.8374U4​ = 1.0574U̇4​ = 0.2869U5​ = 0.9129U̇5​ = −0.4452σ3​ = −0.0567σ̇3​ = −0.2850σ4​ = −0.1263σ̇4​ = −0.6413σj​ 读 Uj−1​, Uj​, Uj+1​权重 −σl​, σl​ − σr​, σr​qL​ = 1.1372q̇L​ = 0.6949UL​ = 1.1656U̇L​ = 0.8374UR​ = 1.0574U̇R​ = 0.2869qR​ = 1.1206q̇R​ = 0.6076ν = 0.010ν̇ = 0.0000H3​ = 0.6625Ḣ3​ = 0.8670R3​ += H3​Ṙ3​ += 0.8670R4​ −= H3​Ṙ4​ −= 0.8670Ḣ3​ = cL​ q̇L​ + cR​ q̇R​ + κf​(U̇L​ − U̇R​) − ν̇(UR​ − UL​)/df​ = 0.8670种子:U̇ = v0​(a 方向的切线解),Ḋ = e0​;ν 不变,所以 ν̇ = 0
图 33 · 一个面的前向数据流(面 f=3f=3,在节点 3 与 4 之间;默认设计,无限制器线性重构;种子 𝐔˙=v0\dot{\mathbf U}=v_0、D˙=e0\dot D=e_0,即第 10 节振幅 aa 方向的切线解)。从左到右是程序顺序:(1)面读入 4 个未知量;(2)面两端节点上的斜率、迹 qL,qRq_L,q_R、未重构状态 UL,URU_L,U_R 和黏性 ν\nu 组成面输入 zfz_f(面的输入向量,不是第 1 节正弦的自变量 z=2π(x−φ)z=2\pi(x-\varphi));(3)通量 HfH_f;(4)分发到 R3R_3、R4R_4。每个方框给出原始值和(绿色的)切向量,每条箭头上是它所乘的局部导数。每个面两侧都有节点,所以所有面用同一段代码;在面 00 和面 N−1N-1 上,被写入的两行之一是约束行,面不向它写入(第 4 节)。
Figure 33 · The forward data flow of one face (face f=3, between nodes 3 and 4; default design, unlimited linear reconstruction; seed U=v_0, D-dot=e_0, the tangent solution of Section 10 for the amplitude a). Left to right in program order: (1) the face gathers four unknowns, (2) the slopes at the two nodes of the face, the traces q_L,q_R, the raw states U_L,U_R and the viscosity ν form the face inputs z_f (the input vector of the face, not the argument z=2π(x-φ) of the sine in Section 1), (3) the flux H_f, (4) the scatter into R_3 and R_4. Each box carries its primal value and, in green, its tangent; each arrow carries the local derivative it multiplies. Every face has a node on each side, so one piece of code serves all faces; on the faces 0 and N-1 one of the two target rows is a constraint row, which the faces do not write (Section 4).(1) gather(2) reconstruct: slopes, traces, raw states, ν(3) flux(4) scatter1111½−½cL​κf​−κf​cR​−(UR​ − UL​)/df​+1−1U2​ = 1.1708U̇2​ = 0.8569U3​ = 1.1656U̇3​ = 0.8374U4​ = 1.0574U̇4​ = 0.2869U5​ = 0.9129U̇5​ = −0.4452σ3​ = −0.0567σ̇3​ = −0.2850σ4​ = −0.1263σ̇4​ = −0.6413σj​ reads Uj−1​, Uj​, Uj+1​with −σl​, σl​ − σr​, σr​qL​ = 1.1372q̇L​ = 0.6949UL​ = 1.1656U̇L​ = 0.8374UR​ = 1.0574U̇R​ = 0.2869qR​ = 1.1206q̇R​ = 0.6076ν = 0.010ν̇ = 0.0000H3​ = 0.6625Ḣ3​ = 0.8670R3​ += H3​Ṙ3​ += 0.8670R4​ −= H3​Ṙ4​ −= 0.8670Ḣ3​ = cL​ q̇L​ + cR​ q̇R​ + κf​(U̇L​ − U̇R​) − ν̇(UR​ − UL​)/df​ = 0.8670seed: U̇ = v0​ (the tangent solution of a), Ḋ = e0​; ν does not move, so ν̇ = 0
Figure 33 · The forward data flow of one face (face f=3f=3, between nodes 3 and 4; default design, unlimited linear reconstruction; seed 𝐔˙=v0\dot{\mathbf U}=v_0, D˙=e0\dot D=e_0, the tangent solution of Section 10 for the amplitude aa). Left to right in program order: (1) the face gathers four unknowns, (2) the slopes at the two nodes of the face, the traces qL,qRq_L,q_R, the raw states UL,URU_L,U_R and the viscosity ν\nu form the face inputs zfz_f (the input vector of the face, not the argument z=2π(x−φ)z=2\pi(x-\varphi) of the sine in Section 1), (3) the flux HfH_f, (4) the scatter into R3R_3 and R4R_4. Each box carries its primal value and, in green, its tangent; each arrow carries the local derivative it multiplies. Every face has a node on each side, so one piece of code serves all faces; on the faces 00 and N−1N-1 one of the two target rows is a constraint row, which the faces do not write (Section 4).

先看最小的一步:一个面的通量

The smallest step first: one face flux

第 3 节的通量有五个输入:两个迹、两个未重构状态和黏性,H=H(qL,qR,UL,UR,ν)H=H(q_L,q_R,U_L,U_R,\nu)(df=hd_f=h 由网格决定,是常数)。对每个输入求偏导,乘以该输入的切向量,再相加:

The flux of Section 3 has five inputs: the two traces, the two raw states and the viscosity, H=H(qL,qR,UL,UR,ν)H=H(q_L,q_R,U_L,U_R,\nu) (df=hd_f=h is fixed by the mesh). Differentiate it with respect to each input, multiply by that input's tangent and add:

H˙f=cL q˙L+cR q˙R⏟H˙c+κf (U˙L−U˙R)−ν˙ UR−ULdf⏟H˙v,cL=qL2+1,cR=qR2−1,κf=νdf.\dot H_f=\underbrace{c_L\,\dot q_L+c_R\,\dot q_R}_{\dot H^c}+\underbrace{\kappa_f\,(\dot U_L-\dot U_R)-\dot\nu\,\frac{U_R-U_L}{d_f}}_{\dot H^v},\qquad c_L=\frac{q_L}2+1,\quad c_R=\frac{q_R}2-1,\quad \kappa_f=\frac{\nu}{d_f}.

对流部分 H˙c\dot H^c 与黏性部分 H˙v\dot H^v 分别是第 3 节 HcH^c、HvH^v 的切向量。五个偏导数在第 3 节都已写出;最后一项值得单独说:黏性是设计变量,在通量中乘以差商 (UR−UL)/df(U_R-U_L)/d_f,所以设计种子 ν˙\dot\nu 直接作用在每一个面上,系数是 −(UR−UL)/df-(U_R-U_L)/d_f;aa 和 φ\varphi 根本不出现在通量里:本页的边界值 uin,uoutu_{\rm in},u_{\rm out} 只进入两个约束行(语句 5),面看不到它们。

The convective part H˙c\dot H^c and the viscous part H˙v\dot H^v are the tangents of the HcH^c and HvH^v of Section 3, where all five partial derivatives were written out. The last term deserves a word of its own: the viscosity is a design variable that multiplies the difference quotient (UR−UL)/df(U_R-U_L)/d_f in the flux, so a design seed ν˙\dot\nu acts directly on every face, with the factor −(UR−UL)/df-(U_R-U_L)/d_f; aa and φ\varphi do not appear in the flux at all: on this page the boundary data uin,uoutu_{\rm in},u_{\rm out} enter only the two constraint rows (statement 5), and the faces never see them.

手算一个面:取默认收敛解(无限制器线性)的面 f=3f=3,这里 cL=1.5686c_L=1.5686,cR=−0.4397c_R=-0.4397,κf=ν/h=0.08\kappa_f=\nu/h=0.08,UR−UL=−0.1082U_R-U_L=-0.1082。(i)只扰动未知量 U3U_3(面的左节点):它在 qLq_L 里的权重是 1,在 qRq_R 里是 14\tfrac14(斜率 σ4=(U5−U3)/2\sigma_4=(U_5-U_3)/2 含有它),在 ULU_L 里是 1、在 URU_R 里是 0,所以 q˙L=1\dot q_L=1,q˙R=14\dot q_R=\tfrac14,U˙L=1\dot U_L=1,U˙R=0\dot U_R=0,ν˙=0\dot\nu=0,H˙3=cL+cR/4+κf=1.5387\dot H_3=c_L+c_R/4+\kappa_f=1.5387,这正是第 3 节面 Jacobian 的元素 ∂H3/∂U3\partial H_3/\partial U_3。(ii)只扰动黏性,ν˙=1\dot\nu=1:所有状态切向量为零,H˙3=−(UR−UL)/df=0.8653\dot H_3=-(U_R-U_L)/d_f=0.8653,这是这个面上 ν\nu 的显式路径。然后像 HfH_f 加到 RfR_f、从 Rf+1R_{f+1} 减去一样,把 H˙f\dot H_f 加到 R˙f\dot R_f、从 R˙f+1\dot R_{f+1} 减去。

Work one face by hand: face f=3f=3 of the converged default solution (unlimited linear), where cL=1.5686c_L=1.5686, cR=−0.4397c_R=-0.4397, κf=ν/h=0.08\kappa_f=\nu/h=0.08 and UR−UL=−0.1082U_R-U_L=-0.1082. (i) Seed only the unknown U3U_3 (the left node of the face): its weight is 1 in qLq_L, 14\tfrac14 in qRq_R (the slope σ4=(U5−U3)/2\sigma_4=(U_5-U_3)/2 contains it), 1 in ULU_L and 0 in URU_R, so q˙L=1\dot q_L=1, q˙R=14\dot q_R=\tfrac14, U˙L=1\dot U_L=1, U˙R=0\dot U_R=0, ν˙=0\dot\nu=0 and H˙3=cL+cR/4+κf=1.5387\dot H_3=c_L+c_R/4+\kappa_f=1.5387: the entry ∂H3/∂U3\partial H_3/\partial U_3 of the face Jacobian of Section 3. (ii) Seed only the viscosity, ν˙=1\dot\nu=1: every state tangent vanishes and H˙3=−(UR−UL)/df=0.8653\dot H_3=-(U_R-U_L)/d_f=0.8653, the explicit ν\nu-path of this face. Then H˙f\dot H_f is added to R˙f\dot R_f and subtracted from R˙f+1\dot R_{f+1}, exactly as HfH_f is added to RfR_f and subtracted from Rf+1R_{f+1}.

从状态切向量到通量切向量:一个面读哪些未知量

From state tangents to flux tangents: which unknowns a face reads

无限制器线性重构时,迹是未知量的固定线性组合(第 3 节),所以迹的切向量是状态切向量的同一组合。对两个节点都是内部节点的面(1≤f≤N−21\le f\le N-2):

With the unlimited linear reconstruction the traces are fixed linear combinations of the unknowns (Section 3), so their tangents are the same combinations of the state tangents. For a face whose two nodes are both interior (1≤f≤N−21\le f\le N-2):

q˙L=−14U˙f−1+U˙f+14U˙f+1,q˙R=14U˙f+U˙f+1−14U˙f+2,U˙L=U˙f,U˙R=U˙f+1,\dot q_L=-\tfrac14\dot U_{f-1}+\dot U_f+\tfrac14\dot U_{f+1},\qquad \dot q_R=\tfrac14\dot U_f+\dot U_{f+1}-\tfrac14\dot U_{f+2},\qquad \dot U_L=\dot U_f,\quad \dot U_R=\dot U_{f+1},
H˙f=−cL4U˙f−1+(cL+cR4+κf)U˙f+(cL4+cR−κf)U˙f+1−cR4U˙f+2−ν˙ Uf+1−Ufh.\dot H_f=-\frac{c_L}4\dot U_{f-1}+\Big(c_L+\frac{c_R}4+\kappa_f\Big)\dot U_f+\Big(\frac{c_L}4+c_R-\kappa_f\Big)\dot U_{f+1}-\frac{c_R}4\dot U_{f+2}-\dot\nu\,\frac{U_{f+1}-U_f}h.

四个系数就是第 3 节面 Jacobian ∂Hf/∂Uj\partial H_f/\partial U_j 的第 ff 行:面 3 上是 −0.3922-0.3922、1.53871.5387、−0.1276-0.1276、0.10990.1099。黏性部分给中间两个系数中左边的加 +κf+\kappa_f、右边的加 −κf-\kappa_f,不扩大模板。在默认状态下,每个面 1≤f≤N−21\le f\le N-2 上都有 cL+cR/4>0c_L+c_R/4>0 和 cL/4+cR<0c_L/4+c_R<0,所以这两项都被加强;但这不是对每个状态都成立:cL/4+cRc_L/4+c_R 可以变正,这时 −κf-\kappa_f 把它拉向零。只要 κf<2(cL/4+cR)\kappa_f<2(c_L/4+c_R),它的绝对值就变小(κf\kappa_f 超过 cL/4+cRc_L/4+c_R 时已经变号;D=(0.45,0.61,0.01)D=(0.45,0.61,0.01)、N=8N=8 时面 6 上 0.120→0.0400.120\to0.040);否则它变号且绝对值变大(同一状态的面 5 上 0.0189→−0.0610.0189\to-0.061)。靠近边界时面也没有特例:边界节点的斜率是单侧差 σ0=U1−U0\sigma_0=U_1-U_0(第 3 节),所以 qL=12(U0+U1)q_L=\tfrac12(U_0+U_1),面 0 读 U0,U1,U2U_0,U_1,U_2(q˙L=12(U˙0+U˙1)\dot q_L=\tfrac12(\dot U_0+\dot U_1)),面 N−1N-1 对称地读 UN−2,UN−1,UNU_{N-2},U_{N-1},U_N。一阶时 σ≡0\sigma\equiv0,每个面只读自己的两个节点 Uf,Uf+1U_f,U_{f+1}。光滑限制器时 qLq_L 中的权重不再是 −14,1,14-\tfrac14,1,\tfrac14,而是 −σl/2, 1+(σl−σr)/2, σr/2-\sigma_l/2,\ 1+(\sigma_l-\sigma_r)/2,\ \sigma_r/2,其中 σl,σr\sigma_l,\sigma_r 是节点 ff 上随状态变化的偏导数(下表语句 1b;qRq_R 同理);边界节点的单侧差仍是线性的,所以两个边界节点上限制器什么也不改变。图 34 显示,在默认解的面 3 上,这些权重与 −14,1,14-\tfrac14,1,\tfrac14 相差很远。

The four coefficients are row ff of the face Jacobian ∂Hf/∂Uj\partial H_f/\partial U_j of Section 3: at face 3 they are −0.3922-0.3922, 1.53871.5387, −0.1276-0.1276 and 0.10990.1099. The viscous part adds +κf+\kappa_f to the left and −κf-\kappa_f to the right central coefficient and widens nothing. At the default state cL+cR/4>0c_L+c_R/4>0 and cL/4+cR<0c_L/4+c_R<0 on every face 1≤f≤N−21\le f\le N-2, so both entries are strengthened; this does not hold for every state: cL/4+cRc_L/4+c_R can turn positive, and −κf-\kappa_f then pulls it towards zero. Its magnitude shrinks while κf<2(cL/4+cR)\kappa_f<2(c_L/4+c_R) (the sign already flips once κf\kappa_f exceeds cL/4+cRc_L/4+c_R; face 6 for D=(0.45,0.61,0.01)D=(0.45,0.61,0.01), N=8N=8: 0.120→0.0400.120\to0.040); beyond that it changes sign and grows in magnitude (face 5 of the same state: 0.0189→−0.0610.0189\to-0.061). Next to a boundary the faces are not special either: the slope at a boundary node is the one-sided difference σ0=U1−U0\sigma_0=U_1-U_0 (Section 3), so qL=12(U0+U1)q_L=\tfrac12(U_0+U_1), face 0 reads U0,U1,U2U_0,U_1,U_2 (q˙L=12(U˙0+U˙1)\dot q_L=\tfrac12(\dot U_0+\dot U_1)) and face N−1N-1 reads UN−2,UN−1,UNU_{N-2},U_{N-1},U_N symmetrically. At first order σ≡0\sigma\equiv0 and every face reads only its own two nodes Uf,Uf+1U_f,U_{f+1}. With the smooth limiter the weights in qLq_L are no longer −14,1,14-\tfrac14,1,\tfrac14 but −σl/2, 1+(σl−σr)/2, σr/2-\sigma_l/2,\ 1+(\sigma_l-\sigma_r)/2,\ \sigma_r/2 with the state-dependent partial derivatives σl,σr\sigma_l,\sigma_r at node ff (statement 1b in the table below; qRq_R alike); the one-sided differences of the two boundary nodes stay linear, so the limiter changes nothing at the boundary nodes themselves. Figure 34 shows that at face 3 of the default solution these weights are far from −14,1,14-\tfrac14,1,\tfrac14.

图 34 · 一个面的切向量读哪些未知量(默认设计,各重构自己的收敛解)。每行是面两侧的四个节点;格子上方是该节点在 q-dot_L、q-dot_R 中的权重(未重构状态 U-dot_L=U-dot_f、U-dot_R=U-dot_(f+1) 的权重总是 1),格子里是前向计算中与 U-dot_j 相乘的导数 ∂ H_f/∂ U_j(蓝正橙负,白色为零)。前三行是面 f=3:一阶读 2 个未知量;无限制器线性读 4 个,权重固定为 ± 1/4;光滑限制器同样 4 个,权重随状态变化(这里 q_L 中是 -0.61 与 1.62,而不是 -1/4 与 1)。第四行是无限制器线性解的边界面 f=0:没有节点 -1,节点 0 的单侧斜率使它读 3 个未知量,它的代码与其他面完全相同。面 f 的切向量读哪些未知量:∂Hf​/∂Uj​(格子里)与迹的权重(格子上方)一阶面 f = 3读 2 个未知量q̇L​: 0.000 q̇R​: 0.000U2​0q̇L​: 1.000 q̇R​: 0.000U3​∂H3​/∂U3​ = 1.5567q̇L​: 0.000 q̇R​: 1.000U4​∂H3​/∂U4​ = −0.6733q̇L​: 0.000 q̇R​: 0.000U5​0f = 3无限制器线性面 f = 3读 4 个未知量q̇L​: −0.250 q̇R​: 0.000U2​∂H3​/∂U2​ = −0.3922q̇L​: 1.000 q̇R​: 0.250U3​∂H3​/∂U3​ = 1.5387q̇L​: 0.250 q̇R​: 1.000U4​∂H3​/∂U4​ = −0.1276q̇L​: 0.000 q̇R​: −0.250U5​∂H3​/∂U5​ = 0.1099f = 3光滑限制器面 f = 3读 4 个未知量q̇L​: −0.615 q̇R​: 0.000U2​∂H3​/∂U2​ = −0.9651q̇L​: 1.618 q̇R​: 0.428U3​∂H3​/∂U3​ = 2.4298q̇L​: −0.003 q̇R​: 0.672U4​∂H3​/∂U4​ = −0.3821q̇L​: 0.000 q̇R​: −0.100U5​∂H3​/∂U5​ = 0.0444f = 3无限制器线性边界面 f = 0读 3 个未知量(无此节点)q̇L​: 0.500 q̇R​: 0.250U0​∂H0​/∂U0​ = 0.7039q̇L​: 0.500 q̇R​: 1.000U1​∂H0​/∂U1​ = 0.1712q̇L​: 0.000 q̇R​: −0.250U2​∂H0​/∂U2​ = 0.1242f = 0未重构状态 UL​ = Uf​、UR​ = Uf+1​ 的权重总是 1(黏性通量 ±κf​);一阶 σ ≡ 0。光滑限制器内部节点的权重随状态变化;端点的 σ 是线性的单侧差。
图 34 · 一个面的切向量读哪些未知量(默认设计,各重构自己的收敛解)。每行是面两侧的四个节点;格子上方是该节点在 q˙L\dot q_L、q˙R\dot q_R 中的权重(未重构状态 U˙L=U˙f\dot U_L=\dot U_f、U˙R=U˙f+1\dot U_R=\dot U_{f+1} 的权重总是 1),格子里是前向计算中与 U˙j\dot U_j 相乘的导数 ∂Hf/∂Uj\partial H_f/\partial U_j(蓝正橙负,白色为零)。前三行是面 f=3f=3:一阶读 2 个未知量;无限制器线性读 4 个,权重固定为 ±14\pm\tfrac14;光滑限制器同样 4 个,权重随状态变化(这里 qLq_L 中是 −0.61-0.61 与 1.621.62,而不是 −14-\tfrac14 与 1)。第四行是无限制器线性解的边界面 f=0f=0:没有节点 −1-1,节点 0 的单侧斜率使它读 3 个未知量,它的代码与其他面完全相同。
Figure 34 · Which unknowns the tangent of one face reads (default design, each reconstruction's own converged solution). Each row shows the four nodes around the face; above a node its weights in q-dot_L and q-dot_R (the raw states U-dot_L=U-dot_f, U-dot_R=U-dot_(f+1) always have weight 1), inside it the derivative ∂ H_f/∂ U_j that the forward computation multiplies by U-dot_j (blue positive, orange negative, white zero). The first three rows are face f=3: first order reads two unknowns; unlimited linear four, with the fixed weights ± 1/4; smooth limiter the same four with weights that depend on the state (here -0.61 and 1.62 in q_L instead of -1/4 and 1). The fourth row is the boundary face f=0 of the unlimited linear solution: there is no node -1, the one-sided slope at node 0 makes it read three unknowns, and its code is the code of every other face.What the tangent of face f reads: ∂Hf​/∂Uj​ (inside) and the weights of the traces (above)first orderface f = 3reads 2 unknownsq̇L​: 0.000 q̇R​: 0.000U2​0q̇L​: 1.000 q̇R​: 0.000U3​∂H3​/∂U3​ = 1.5567q̇L​: 0.000 q̇R​: 1.000U4​∂H3​/∂U4​ = −0.6733q̇L​: 0.000 q̇R​: 0.000U5​0f = 3unlimited linearface f = 3reads 4 unknownsq̇L​: −0.250 q̇R​: 0.000U2​∂H3​/∂U2​ = −0.3922q̇L​: 1.000 q̇R​: 0.250U3​∂H3​/∂U3​ = 1.5387q̇L​: 0.250 q̇R​: 1.000U4​∂H3​/∂U4​ = −0.1276q̇L​: 0.000 q̇R​: −0.250U5​∂H3​/∂U5​ = 0.1099f = 3smooth limiterface f = 3reads 4 unknownsq̇L​: −0.615 q̇R​: 0.000U2​∂H3​/∂U2​ = −0.9651q̇L​: 1.618 q̇R​: 0.428U3​∂H3​/∂U3​ = 2.4298q̇L​: −0.003 q̇R​: 0.672U4​∂H3​/∂U4​ = −0.3821q̇L​: 0.000 q̇R​: −0.100U5​∂H3​/∂U5​ = 0.0444f = 3unlimited linearboundary face f = 0reads 3 unknowns(no such node)q̇L​: 0.500 q̇R​: 0.250U0​∂H0​/∂U0​ = 0.7039q̇L​: 0.500 q̇R​: 1.000U1​∂H0​/∂U1​ = 0.1712q̇L​: 0.000 q̇R​: −0.250U2​∂H0​/∂U2​ = 0.1242f = 0The raw states UL​ = Uf​, UR​ = Uf+1​ always have weight 1 (viscous flux ±κf​); first order σ ≡ 0.The smooth-limiter weights at interior nodes change with the state; the slope at an end node is the linear one-sided difference.
Figure 34 · Which unknowns the tangent of one face reads (default design, each reconstruction's own converged solution). Each row shows the four nodes around the face; above a node its weights in q˙L\dot q_L and q˙R\dot q_R (the raw states U˙L=U˙f\dot U_L=\dot U_f, U˙R=U˙f+1\dot U_R=\dot U_{f+1} always have weight 1), inside it the derivative ∂Hf/∂Uj\partial H_f/\partial U_j that the forward computation multiplies by U˙j\dot U_j (blue positive, orange negative, white zero). The first three rows are face f=3f=3: first order reads two unknowns; unlimited linear four, with the fixed weights ±14\pm\tfrac14; smooth limiter the same four with weights that depend on the state (here −0.61-0.61 and 1.621.62 in qLq_L instead of −14-\tfrac14 and 1). The fourth row is the boundary face f=0f=0 of the unlimited linear solution: there is no node −1-1, the one-sided slope at node 0 makes it read three unknowns, and its code is the code of every other face.

逐句求导:残差代码的前向语句

The residual code differentiated statement by statement

前向模式对第 5 节残差代码的每条赋值语句 y=ϕ(x1,…,xm)y=\phi(x_1,\dots,x_m)(这里 ϕ\phi 是任意初等函数,不是设计的相位 φ\varphi)应用一次链式法则,y˙=∑k(∂ϕ/∂xk) x˙k\dot y=\sum_k(\partial\phi/\partial x_k)\,\dot x_k,紧跟在原语句之后,按同样的顺序执行。下表对本页代码的每条语句都这样做,同时允许状态种子 𝐔˙\dot{\mathbf U} 与设计种子 D˙\dot D 都不为零(语句 0 是组装前的置零;语句 1c、2、3 在面循环 f=0,…,N−1f=0,\dots,N-1 里):

Forward mode applies the chain rule once to every assignment y=ϕ(x1,…,xm)y=\phi(x_1,\dots,x_m) of the residual code of Section 5 (here ϕ\phi is any elementary function, not the phase φ\varphi of the design), y˙=∑k(∂ϕ/∂xk) x˙k\dot y=\sum_k(\partial\phi/\partial x_k)\,\dot x_k, placed after it and executed in the same order. The table does it for every statement of this page's code, with a state seed 𝐔˙\dot{\mathbf U} and a design seed D˙\dot D both allowed (statement 0 is the zeroing before the assembly; statements 1c, 2 and 3 run inside the face loop f=0,…,N−1f=0,\dots,N-1):

#原始语句Primal statement前向语句(同一顺序)Tangent statement (same order)所用局部导数Local derivative used
0R←0R\leftarrow0R˙←0\dot R\leftarrow0—
1alj=Uj−Uj−1,  rj=Uj+1−Uj  (1≤j≤N−1)l_j=U_j-U_{j-1},\ \ r_j=U_{j+1}-U_j\ \ (1\le j\le N-1)l˙j=U˙j−U˙j−1,  r˙j=U˙j+1−U˙j\dot l_j=\dot U_j-\dot U_{j-1},\ \ \dot r_j=\dot U_{j+1}-\dot U_j±1\pm1
1bσj=σ(lj,rj)  (1≤j≤N−1)\sigma_j=\sigma(l_j,r_j)\ \ (1\le j\le N-1);σ0=U1−U0\sigma_0=U_1-U_0,σN=UN−UN−1\sigma_N=U_N-U_{N-1}(一阶:σ0=σN=0\sigma_0=\sigma_N=0)σj=σ(lj,rj)  (1≤j≤N−1)\sigma_j=\sigma(l_j,r_j)\ \ (1\le j\le N-1); σ0=U1−U0\sigma_0=U_1-U_0, σN=UN−UN−1\sigma_N=U_N-U_{N-1} (first order: σ0=σN=0\sigma_0=\sigma_N=0)σ˙j=σl l˙j+σr r˙j;  σ˙0=U˙1−U˙0,  σ˙N=U˙N−U˙N−1\dot\sigma_j=\sigma_l\,\dot l_j+\sigma_r\,\dot r_j;\ \ \dot\sigma_0=\dot U_1-\dot U_0,\ \ \dot\sigma_N=\dot U_N-\dot U_{N-1}(σl,σr)(\sigma_l,\sigma_r):一阶 (0,0)(0,0),无限制器 (12,12)(\tfrac12,\tfrac12),光滑限制器随状态变化(第 3 节);两个端点 ±1\pm1(σl,σr)(\sigma_l,\sigma_r): (0,0)(0,0) first order, (12,12)(\tfrac12,\tfrac12) unlimited, state-dependent for the smooth limiter (Section 3); ±1\pm1 at the two end nodes
1cqL=Uf+12σf, UL=Uf;  qR=Uf+1−12σf+1, UR=Uf+1  (0≤f≤N−1)q_L=U_f+\tfrac12\sigma_f,\ U_L=U_f;\ \ q_R=U_{f+1}-\tfrac12\sigma_{f+1},\ U_R=U_{f+1}\ \ (0\le f\le N-1)q˙L=U˙f+12σ˙f, U˙L=U˙f;  q˙R=U˙f+1−12σ˙f+1, U˙R=U˙f+1\dot q_L=\dot U_f+\tfrac12\dot\sigma_f,\ \dot U_L=\dot U_f;\ \ \dot q_R=\dot U_{f+1}-\tfrac12\dot\sigma_{f+1},\ \dot U_R=\dot U_{f+1}1, ±121,\ \pm\tfrac12
2Hf=14(qL2+qR2)−(qR−qL)−ν UR−ULdfH_f=\tfrac14(q_L^2+q_R^2)-(q_R-q_L)-\nu\,\frac{U_R-U_L}{d_f}H˙f=cLq˙L+cRq˙R+κf(U˙L−U˙R)−ν˙ UR−ULdf\dot H_f=c_L\dot q_L+c_R\dot q_R+\kappa_f(\dot U_L-\dot U_R)-\dot\nu\,\frac{U_R-U_L}{d_f}cL, cR, ±κf, −UR−ULdfc_L,\ c_R,\ \pm\kappa_f,\ -\frac{U_R-U_L}{d_f}
3Rf+=Hf (f≥1);  Rf+1-=Hf (f≤N−2)R_f\mathrel{\text{+=}}H_f\ (f\ge1);\ \ R_{f+1}\mathrel{\text{-=}}H_f\ (f\le N-2)R˙f+=H˙f;  R˙f+1-=H˙f\dot R_f\mathrel{\text{+=}}\dot H_f;\ \ \dot R_{f+1}\mathrel{\text{-=}}\dot H_f±1\pm1
4Qf=q∗(xf+1/2;D) (0≤f≤N−1);  Rj-=Qj−Qj−1 (1≤j≤N−1)Q_f=q^*(x_{f+1/2};D)\ (0\le f\le N-1);\ \ R_j\mathrel{\text{-=}}Q_j-Q_{j-1}\ (1\le j\le N-1)Q˙f=∂Q∂aa˙+∂Q∂φφ˙+∂Q∂νν˙;  R˙j-=Q˙j−Q˙j−1\dot Q_f=\frac{\partial Q}{\partial a}\dot a+\frac{\partial Q}{\partial\varphi}\dot\varphi+\frac{\partial Q}{\partial\nu}\dot\nu;\ \ \dot R_j\mathrel{\text{-=}}\dot Q_j-\dot Q_{j-1}∂Q/∂D\partial Q/\partial D(见下式);∓1\mp1∂Q/∂D\partial Q/\partial D (below); ∓1\mp1
5uin=u∗(0;D), uout=u∗(1;D);  R0=U0−uin, RN=UN−uoutu_{\rm in}=u^*(0;D),\ u_{\rm out}=u^*(1;D);\ \ R_0=U_0-u_{\rm in},\ R_N=U_N-u_{\rm out}u˙in=∂uin∂aa˙+∂uin∂φφ˙\dot u_{\rm in}=\frac{\partial u_{\rm in}}{\partial a}\dot a+\frac{\partial u_{\rm in}}{\partial\varphi}\dot\varphi,u˙out\dot u_{\rm out} 同理;R˙0=U˙0−u˙in\dot R_0=\dot U_0-\dot u_{\rm in},R˙N=U˙N−u˙out\dot R_N=\dot U_N-\dot u_{\rm out}u˙in=∂uin∂aa˙+∂uin∂φφ˙\dot u_{\rm in}=\frac{\partial u_{\rm in}}{\partial a}\dot a+\frac{\partial u_{\rm in}}{\partial\varphi}\dot\varphi, u˙out\dot u_{\rm out} alike; R˙0=U˙0−u˙in\dot R_0=\dot U_0-\dot u_{\rm in}, R˙N=U˙N−u˙out\dot R_N=\dot U_N-\dot u_{\rm out}∂uin∂a=−sin⁡2πφ\frac{\partial u_{\rm in}}{\partial a}=-\sin2\pi\varphi,∂uin∂φ=−2πa cos⁡2πφ\frac{\partial u_{\rm in}}{\partial\varphi}=-2\pi a\,\cos2\pi\varphi(uoutu_{\rm out} 相同);1, −11,\ -1∂uin∂a=−sin⁡2πφ\frac{\partial u_{\rm in}}{\partial a}=-\sin2\pi\varphi, ∂uin∂φ=−2πa cos⁡2πφ\frac{\partial u_{\rm in}}{\partial\varphi}=-2\pi a\,\cos2\pi\varphi (the same for uoutu_{\rm out}); 1, −11,\ -1

语句 4 的精确通量偏导数来自 Qf=q∗(xf+1/2;D)=12(u∗)2−νux∗Q_f=q^*(x_{f+1/2};D)=\tfrac12(u^*)^2-\nu u^*_x,其中 u∗=1+a sin⁡zu^*=1+a\,\sin z,ux∗=2πa cos⁡zu^*_x=2\pi a\,\cos z,z=2π(xf+1/2−φ)z=2\pi(x_{f+1/2}-\varphi):

The exact-flux partial derivatives of statement 4 come from Qf=q∗(xf+1/2;D)=12(u∗)2−νux∗Q_f=q^*(x_{f+1/2};D)=\tfrac12(u^*)^2-\nu u^*_x, with u∗=1+a sin⁡zu^*=1+a\,\sin z, ux∗=2πa cos⁡zu^*_x=2\pi a\,\cos z and z=2π(xf+1/2−φ)z=2\pi(x_{f+1/2}-\varphi):

∂Q∂a=u∗sin⁡z−2πνcos⁡z,∂Q∂φ=−2πa u∗cos⁡z−4π2νa sin⁡z,∂Q∂ν=−2πa cos⁡z.\frac{\partial Q}{\partial a}=u^*\sin z-2\pi\nu\cos z,\qquad \frac{\partial Q}{\partial\varphi}=-2\pi a\,u^*\cos z-4\pi^2\nu a\,\sin z,\qquad \frac{\partial Q}{\partial\nu}=-2\pi a\,\cos z.

设计进入代码的地方恰好有三处,每处是表中的一行:(i)边界值 uin,uoutu_{\rm in},u_{\rm out} 依赖 aa 和 φ\varphi,只进入两个约束行(语句 5),面循环根本看不到它们;(ii)黏性进入每个面的通量(语句 2),通过 κf=ν/df\kappa_f=\nu/d_f 和显式项 −ν˙(UR−UL)/df-\dot\nu(U_R-U_L)/d_f;(iii)精确通量 QfQ_f(语句 4)依赖全部三个分量,通过源项进入每个内部行。取 𝐔˙=v\dot{\mathbf U}=v、D˙=0\dot D=0,代码返回 AvAv;取 𝐔˙=0\dot{\mathbf U}=0、D˙=ek\dot D=e_k,返回 RDR_D 的第 kk 列 RDekR_De_k。除了原始代码本来就有的数组,前向代码还多存斜率的切向量 σ˙j\dot\sigma_j(s_d)、精确通量的切向量 Q˙f\dot Q_f(Q_d)和输出 R˙\dot R(以及两个数 u˙in\dot u_{\rm in}、u˙out\dot u_{\rm out});局部导数(cL,cR,κf,(UR−UL)/df,σl,σrc_L,c_R,\kappa_f,(U_R-U_L)/d_f,\sigma_l,\sigma_r)算出后立即使用,不必存下(存下 σl,σr\sigma_l,\sigma_r 的是第 9 节的 residual_b)。

The design enters the code in exactly three places, each a row of the table: (i) the boundary data uin,uoutu_{\rm in},u_{\rm out} depend on aa and φ\varphi and enter only the two constraint rows (statement 5): the face loop never sees them; (ii) the viscosity enters the flux of every face (statement 2), through κf=ν/df\kappa_f=\nu/d_f and the explicit term −ν˙(UR−UL)/df-\dot\nu(U_R-U_L)/d_f; (iii) the exact fluxes QfQ_f (statement 4) depend on all three components and enter every interior row through the source. With 𝐔˙=v\dot{\mathbf U}=v and D˙=0\dot D=0 the code returns AvAv; with 𝐔˙=0\dot{\mathbf U}=0 and D˙=ek\dot D=e_k it returns the column RDekR_De_k. Besides the arrays the primal code already has, the tangent code keeps the slope tangents σ˙j\dot\sigma_j (s_d), the exact-flux tangents Q˙f\dot Q_f (Q_d) and the output R˙\dot R (and the two numbers u˙in\dot u_{\rm in}, u˙out\dot u_{\rm out}); the local derivatives (cL,cR,κf,(UR−UL)/df,σl,σrc_L,c_R,\kappa_f,(U_R-U_L)/d_f,\sigma_l,\sigma_r) are used as soon as they are computed and need not be stored (it is the residual_b of Section 9 that keeps σl,σr\sigma_l,\sigma_r).

为什么是同一顺序:一条前向语句需要它的输入的切向量,而这些切向量由前面原始语句的前向语句算出。所以前向代码可以和原始代码逐句交替、按原始顺序运行;必须倒着运行的是第 9 节的反向模式。

Why the same order: a tangent statement needs the tangents of its inputs, and those are computed by the tangent statements of the earlier primal statements. The tangent code can therefore run interleaved with the primal, statement by statement, in the primal's order; it is the reverse mode of Section 9 that must run backwards.

图 35 · 残差代码的五条语句与设计进入的三处。上排:状态沿面循环走过语句 1(斜率与迹)、2(通量)、3(分发)到达 R;语句 4 把精确积分源项写进内部行;语句 5 写两个约束行,读 U_0,U_N 和边界值。紫色箭头是设计 D=(a,φ,ν):ν 进入每个面的通量(语句 2)和源项(语句 4),a,φ 进入源项(语句 4)和边界值(语句 5),仅此三处。前向代码把种子 (U,D-dot) 沿同样的箭头推过去,反向代码(第 9 节)把权重 R-bar 沿反方向拉回来。UN + 1 个值1 斜率与迹σj​, qL​, qR​, UL​, UR​2 通量Hf​3 分发Rj​ += H, −= HRN + 1 行4 精确积分源项Qf​ → Rj​ −= Qj​ − Qj−1​5 约束行R0​ = U0​ − uin​(D), RN​ = UN​ − uout​(D)U0​, UN​D(a, φ, ν)a, φ, νa, φν残差代码的五条语句与设计进入的三处面循环 f = 0, …, N − 1:每个面两侧都有节点(只有分发不写两个约束行)切向量把种子 (U̇, Ḋ) 沿同样的箭头推过去:ν̇ 进入语句 2 与 4,ȧ、φ̇ 进入语句 4 与 5,U̇ 进入语句 1、2、3 与 5。
图 35 · 残差代码的五条语句与设计进入的三处。上排:状态沿面循环走过语句 1(斜率与迹)、2(通量)、3(分发)到达 RR;语句 4 把精确积分源项写进内部行;语句 5 写两个约束行,读 U0,UNU_0,U_N 和边界值。紫色箭头是设计 D=(a,φ,ν)D=(a,\varphi,\nu):ν\nu 进入每个面的通量(语句 2)和源项(语句 4),a,φa,\varphi 进入源项(语句 4)和边界值(语句 5),仅此三处。前向代码把种子 (𝐔˙,D˙)(\dot{\mathbf U},\dot D) 沿同样的箭头推过去,反向代码(第 9 节)把权重 Rˉ\bar R 沿反方向拉回来。
Figure 35 · The five statements of the residual code and the three places where the design enters. Top row: the state goes through statement 1 (slopes and traces), 2 (flux) and 3 (scatter) of the face loop to R; statement 4 writes the exact integrated source into the interior rows; statement 5 writes the two constraint rows and reads U_0, U_N and the boundary data. Violet arrows are the design D=(a,φ,ν): ν enters the flux of every face (statement 2) and the source (statement 4), a and φ the source (statement 4) and the boundary data (statement 5), and nowhere else. The tangent code pushes the seed (U,D-dot) along the same arrows, the reverse code (Section 9) pulls the weights R-bar back along them.UN + 1 values1 slopes, tracesσj​, qL​, qR​, UL​, UR​2 fluxHf​3 scatterRj​ += H, −= HRN + 1 rows4 exact integrated sourceQf​ → Rj​ −= Qj​ − Qj−1​5 constraint rowsR0​ = U0​ − uin​(D), RN​ = UN​ − uout​(D)U0​, UN​D(a, φ, ν)a, φ, νa, φνThe five statements of the residual code and the three places where the design entersface loop f = 0, …, N − 1: a node on each side of every face (only the scatter skips the two constraint rows)The tangent pushes the seed (U̇, Ḋ) along the same arrows: ν̇ enters statements 2 and 4, ȧ and φ̇ statements 4 and 5, U̇ statements 1, 2, 3 and 5.
Figure 35 · The five statements of the residual code and the three places where the design enters. Top row: the state goes through statement 1 (slopes and traces), 2 (flux) and 3 (scatter) of the face loop to RR; statement 4 writes the exact integrated source into the interior rows; statement 5 writes the two constraint rows and reads U0U_0, UNU_N and the boundary data. Violet arrows are the design D=(a,φ,ν)D=(a,\varphi,\nu): ν\nu enters the flux of every face (statement 2) and the source (statement 4), aa and φ\varphi the source (statement 4) and the boundary data (statement 5), and nowhere else. The tangent code pushes the seed (𝐔˙,D˙)(\dot{\mathbf U},\dot D) along the same arrows, the reverse code (Section 9) pulls the weights Rˉ\bar R back along them.

同一个问题的前向代码在本页更短:前向表有 8 行,格心页有 11 行(两边都把置零算在内),面循环里本页是 3 条语句(1c、2、3),格心页是 5 条(语句 5–9)。格心页里单独处理边界面的两条(面 0 取 qL=UL=uinq_L=U_L=u_{\rm in},面 NN 取 qR=UR=uoutq_R=U_R=u_{\rm out})在这里没有对应物:每个面两侧都有节点,取值、重构和通量对所有面是同一段代码,边界值进入单独的约束行(只有分发,即语句 3,不写两个约束行)。下表把两份前向代码放在一起(行数数自两页的表;非零元数是 N=8N=8 的收敛默认解上的 AA):

The forward code of the same problem is shorter here: its tangent table has 8 rows against 11 on the cell-centred page (the zeroing counted in both), and the face loop has 3 statements (1c, 2, 3) against 5 (statements 5–9). The two statements of the cell page that treat the boundary faces separately (face 0 takes qL=UL=uinq_L=U_L=u_{\rm in}, face NN takes qR=UR=uoutq_R=U_R=u_{\rm out}) have no counterpart: every face has a node on each side, so gather, reconstruction and flux are the same code for all faces, and the boundary data enter a constraint row of their own (only the scatter, statement 3, skips the two constraint rows). The table sets the two forward codes side by side (the rows are counted in the two tables; the nonzeros are those of AA at the converged default solution for N=8N=8):

格心页Cell-centred page本页(节点)This page (node-centred)
前向表的行数(含置零)rows of the tangent table (zeroing included)118
面循环里的语句数statements in the face loop5(其中两条在面数据上有边界特例)5 (two with a boundary special case in the face data)3(面数据没有特例)3 (none in the face data)
面循环face loopf=0,…,Nf=0,\dots,N:N+1N+1 个面,其中两个的距离是 h/2h/2f=0,…,Nf=0,\dots,N: N+1N+1 faces, two of them at the distance h/2h/2f=0,…,N−1f=0,\dots,N-1:NN 个面,距离都是 df=hd_f=hf=0,…,N−1f=0,\dots,N-1: NN faces, all at the distance df=hd_f=h
u˙in,u˙out\dot u_{\rm in},\dot u_{\rm out} 进入where u˙in,u˙out\dot u_{\rm in},\dot u_{\rm out} enter两个边界面(作为左、右状态)the two boundary faces (as the left and right state)只进入两个约束行 R˙0,R˙N\dot R_0,\dot R_Nthe two constraint rows R˙0,R˙N\dot R_0,\dot R_N only
未知量与行unknowns and rowsNN 个单元平均,NN 个平衡行NN cell averages, NN balance rowsN+1N+1 个节点值:N−1N-1 个平衡行和 2 个约束行N+1N+1 nodal values: N−1N-1 balance rows and 2 constraint rows
建出整个 AA 的前向扫描次数tangent sweeps that build AANNN+1N+1
AA 的非零元(一阶 | 无限制器线性)nonzeros of AA (first order | unlimited linear)22 | 3423 | 35

写成自动微分工具的代码(原始语句同时执行;a_d, phi_d, nu_d 是 D˙\dot D 的三个分量,xf[f] 是面的位置 xf+1/2x_{f+1/2}):

As code, in the names of an AD tool (the primal statements run alongside; a_d, phi_d, nu_d are the three components of D˙\dot D, xf[f] is the face position xf+1/2x_{f+1/2}):

residual_d(U, u_d, D, D_d) -> res, res_d
 0  res = 0;  res_d = 0;  s = 0;  s_d = 0               (一阶时 s[0] = s[N] = 0 保持不变)
    for j = 1 .. N-1:
 1a   l = U[j] - U[j-1];        l_d = u_d[j] - u_d[j-1]
      r = U[j+1] - U[j];        r_d = u_d[j+1] - u_d[j]
 1b   s[j] = sigma(l, r);       s_d[j] = sl(l, r)*l_d + sr(l, r)*r_d
    s[0] = U[1] - U[0];         s_d[0] = u_d[1] - u_d[0]       (二阶:端点节点用
    s[N] = U[N] - U[N-1];       s_d[N] = u_d[N] - u_d[N-1]      单侧差)
    for f = 0 .. N-1:
 1c   qL = U[f] + s[f]/2;       qL_d = u_d[f] + s_d[f]/2;      UL = U[f];    UL_d = u_d[f]
      qR = U[f+1] - s[f+1]/2;   qR_d = u_d[f+1] - s_d[f+1]/2;  UR = U[f+1];  UR_d = u_d[f+1]
 2    cL = qL/2 + 1;  cR = qR/2 - 1;  kappa = nu/h
      H   = (qL^2 + qR^2)/4 - (qR - qL) - nu*(UR - UL)/h
      H_d = cL*qL_d + cR*qR_d + kappa*(UL_d - UR_d) - nu_d*(UR - UL)/h
 3    if f >= 1:    res[f]   += H;   res_d[f]   += H_d
      if f <= N-2:  res[f+1] -= H;   res_d[f+1] -= H_d
    for f = 0 .. N-1:
 4a   Q[f] = q*(xf[f]; D);  Q_d[f] = dQda(xf[f])*a_d + dQdphi(xf[f])*phi_d + dQdnu(xf[f])*nu_d
    for j = 1 .. N-1:
 4b   res[j] -= Q[j] - Q[j-1];  res_d[j] -= Q_d[j] - Q_d[j-1]
 5    uin = u*(0; D);  uout = u*(1; D)
      uin_d = -sin(2 pi phi)*a_d - 2 pi a cos(2 pi phi)*phi_d;  uout_d = uin_d
      res[0] = U[0] - uin;   res_d[0] = u_d[0] - uin_d
      res[N] = U[N] - uout;  res_d[N] = u_d[N] - uout_d
residual_d(U, u_d, D, D_d) -> res, res_d
 0  res = 0;  res_d = 0;  s = 0;  s_d = 0               (s[0] = s[N] = 0 stay at first order)
    for j = 1 .. N-1:
 1a   l = U[j] - U[j-1];        l_d = u_d[j] - u_d[j-1]
      r = U[j+1] - U[j];        r_d = u_d[j+1] - u_d[j]
 1b   s[j] = sigma(l, r);       s_d[j] = sl(l, r)*l_d + sr(l, r)*r_d
    s[0] = U[1] - U[0];         s_d[0] = u_d[1] - u_d[0]       (second order: the one-sided
    s[N] = U[N] - U[N-1];       s_d[N] = u_d[N] - u_d[N-1]      differences of the end nodes)
    for f = 0 .. N-1:
 1c   qL = U[f] + s[f]/2;       qL_d = u_d[f] + s_d[f]/2;      UL = U[f];    UL_d = u_d[f]
      qR = U[f+1] - s[f+1]/2;   qR_d = u_d[f+1] - s_d[f+1]/2;  UR = U[f+1];  UR_d = u_d[f+1]
 2    cL = qL/2 + 1;  cR = qR/2 - 1;  kappa = nu/h
      H   = (qL^2 + qR^2)/4 - (qR - qL) - nu*(UR - UL)/h
      H_d = cL*qL_d + cR*qR_d + kappa*(UL_d - UR_d) - nu_d*(UR - UL)/h
 3    if f >= 1:    res[f]   += H;   res_d[f]   += H_d
      if f <= N-2:  res[f+1] -= H;   res_d[f+1] -= H_d
    for f = 0 .. N-1:
 4a   Q[f] = q*(xf[f]; D);  Q_d[f] = dQda(xf[f])*a_d + dQdphi(xf[f])*phi_d + dQdnu(xf[f])*nu_d
    for j = 1 .. N-1:
 4b   res[j] -= Q[j] - Q[j-1];  res_d[j] -= Q_d[j] - Q_d[j-1]
 5    uin = u*(0; D);  uout = u*(1; D)
      uin_d = -sin(2 pi phi)*a_d - 2 pi a cos(2 pi phi)*phi_d;  uout_d = uin_d
      res[0] = U[0] - uin;   res_d[0] = u_d[0] - uin_d
      res[N] = U[N] - uout;  res_d[N] = u_d[N] - uout_d

播放器在当前网格上逐面运行这段代码。选一个种子:单位状态种子 eje_j、光滑的测试种子 U˙j=sin⁡(j+0.3)\dot U_j=\sin(j+0.3),或设计种子 D˙=ek\dot D=e_k;逐条语句前进,看 R˙\dot R 一点点填满(虚线框是最终值 A𝐔˙+RDD˙A\dot{\mathbf U}+R_D\dot D)。

The player runs this code on the current mesh, face by face. Choose a seed: a unit state seed eje_j, the smooth test seed U˙j=sin⁡(j+0.3)\dot U_j=\sin(j+0.3), or a design seed D˙=ek\dot D=e_k; step through the statements and watch R˙\dot R fill up (dashed frames: the final values A𝐔˙+RDD˙A\dot{\mathbf U}+R_D\dot D).

种子:A 的每一列是一次前向扫描

Seeds: every column of A is one tangent sweep

取种子 𝐔˙=ej\dot{\mathbf U}=e_j,代码返回 R˙=Aej\dot R=Ae_j,即 Jacobian 的第 jj 列:所有残差对一个未知量的导数。这次扫描碰到的面是模板含 jj 的那些面(一阶 2 个,端点 1 个;二阶 4 个,节点 11 与 N−1N-1 为 3 个,端点为 2 个),每个面写入它的两行(边界节点的行是约束行,面不写),所以这一列至多有 3 个(一阶)或 5 个(二阶)非零元:AA 的带宽来自一个面的模板。端点列 j=0,Nj=0,N 另有语句 5 给出的单位元。用 e0,…,eNe_0,\dots,e_N 做 N+1N+1 次扫描得到整个 AA,再用 D˙=e0,e1,e2\dot D=e_0,e_1,e_2 做三次得到 RDR_D。下表列出各种子产生非零 R˙\dot R 的语句和 N=8N=8 时 R˙\dot R 的非零元个数(计数来自前向代码本身):

With the seed 𝐔˙=ej\dot{\mathbf U}=e_j the code returns R˙=Aej\dot R=Ae_j, column jj of the Jacobian: the derivatives of all residuals with respect to one unknown. The faces it touches are those whose stencil contains jj (at first order two, and one at an end node; at second order four, three at nodes 11 and N−1N-1, two at the end nodes), and each touched face writes its two target rows (the row of a boundary node is a constraint row, which the faces do not write), so the column has at most 3 (first order) or 5 (second order) nonzero entries: the bandwidth of AA comes from the stencil of one face. The end columns j=0,Nj=0,N also hold the unit entry of statement 5. N+1N+1 sweeps with the seeds e0,…,eNe_0,\dots,e_N build all of AA; three more with D˙=e0,e1,e2\dot D=e_0,e_1,e_2 build RDR_D. The table lists, for each kind of seed, the statements that make R˙\dot R nonzero and the number of nonzero entries of R˙\dot R for N=8N=8 (the counts come from the tangent code itself):

种子Seed产生非零 Ṙ 的语句Statements that make Ṙ nonzeroṘ 的非零元个数(一阶 | 无限制器线性)Nonzero entries of Ṙ (first order | unlimited linear)
𝐔˙=ej,  3≤j≤N−3\dot{\mathbf U}=e_j,\ \ 3\le j\le N-31, 2, 33 | 5
𝐔˙=ej,  j=2, N−2\dot{\mathbf U}=e_j,\ \ j=2,\ N-21, 2, 33 | 4
𝐔˙=ej,  j=1, N−1\dot{\mathbf U}=e_j,\ \ j=1,\ N-11, 2, 32 | 3
𝐔˙=ej,  j=0, N\dot{\mathbf U}=e_j,\ \ j=0,\ N1、2、3 和 5(约束行 R˙0=U˙0\dot R_0=\dot U_0)1, 2, 3 and 5 (the constraint row R˙0=U˙0\dot R_0=\dot U_0)2 | 3
D˙=e0 (a),  e1 (φ)\dot D=e_0\ (a),\ \ e_1\ (\varphi)4 和 5(源项与边界值)4 and 5 (the source and the boundary data)9 | 9
D˙=e2 (ν)\dot D=e_2\ (\nu)2、3 和 4(每个面的显式项与源项;约束行不动)2, 3 and 4 (the explicit term of every face and the source; the constraint rows do not move)7 | 7

播放器在当前网格上逐列演示。设计种子 e0,e1e_0,e_1 的列是满的:源项进入每个内部行,边界值进入两个约束行;ν\nu 的列少两行,因为 ν\nu 不进入约束行。

The player steps through these sweeps on the current mesh. The columns of the design seeds e0,e1e_0,e_1 are full: the source enters every interior row and the boundary data both constraint rows; the column of ν\nu lacks two rows, because ν\nu does not enter the constraint rows.

用本页的数字看两个面

Two faces with the page's own numbers

取默认网格(N=8N=8)、设计种子 D˙=e0\dot D=e_0(振幅 aa),𝐔˙=v0\dot{\mathbf U}=v_0 取第 10 节这个方向的切线解(Av0=−RDe0Av_0=-R_De_0),看内部面 f=3f=3(x3+1/2=0.4375x_{3+1/2}=0.4375,节点 3 与 4 之间)和边界面 f=0f=0(x1/2=0.0625x_{1/2}=0.0625,节点 0 与 1 之间)。每种重构有自己的收敛解和自己的 v0v_0,所以连原始值也不同:

Take the default mesh (N=8N=8), the design seed D˙=e0\dot D=e_0 (the amplitude aa) and for 𝐔˙=v0\dot{\mathbf U}=v_0 the solution of the tangent solve of Section 10 for that direction (Av0=−RDe0Av_0=-R_De_0), and look at the interior face f=3f=3 (x3+1/2=0.4375x_{3+1/2}=0.4375, between nodes 3 and 4) and the boundary face f=0f=0 (x1/2=0.0625x_{1/2}=0.0625, between nodes 0 and 1). Each reconstruction has its own converged solution and its own v0v_0, so even the primal values differ:

内部面 f=3f=3,种子 (𝐔˙,D˙)=(v0,e0)(\dot{\mathbf U},\dot D)=(v_0,e_0)Interior face f=3f=3, seed (𝐔˙,D˙)=(v0,e0)(\dot{\mathbf U},\dot D)=(v_0,e_0)
量Quantity公式Formula一阶first order无限制器线性unlimited linear光滑限制器smooth limiter
qLq_LUf+12σfU_f+\tfrac12\sigma_f0.9533441.1372011.138732
qRq_RUf+1−12σf+1U_{f+1}-\tfrac12\sigma_{f+1}0.8133681.1205541.115342
UL, URU_L,\ U_RUf, Uf+1U_f,\ U_{f+1}0.95334, 0.813371.16556, 1.057391.16425, 1.05090
cL, cRc_L,\ c_RqL/2+1, qR/2−1q_L/2+1,\ q_R/2-11.4767, −0.59331.5686, −0.43971.5694, −0.4423
HfH_fHc+HvH^c+H^v0.5437820.6625170.667633
q˙L\dot q_LU˙f+12σ˙f\dot U_f+\tfrac12\dot\sigma_f−0.3072770.6949390.705642
q˙R\dot q_RU˙f+1−12σ˙f+1\dot U_{f+1}-\tfrac12\dot\sigma_{f+1}−1.1048000.6075620.581346
U˙L, U˙R\dot U_L,\ \dot U_Rv0,f, v0,f+1v_{0,f},\ v_{0,f+1}−0.30728, −1.104800.83744, 0.286910.83652, 0.24290
H˙f\dot H_fcLq˙L+cRq˙R+κf(U˙L−U˙R)c_L\dot q_L+c_R\dot q_R+\kappa_f(\dot U_L-\dot U_R)0.2655500.8669660.897754
Q˙f\dot Q_f∂Q/∂a\partial Q/\partial a0.8913290.8913290.891329
H˙f−Q˙f\dot H_f-\dot Q_f−0.625779−0.0243620.006425
边界面 f=0f=0,同一个种子Boundary face f=0f=0, the same seed
量Quantity公式Formula一阶first order无限制器线性unlimited linear光滑限制器smooth limiter
qLq_LU0+12σ0U_0+\tfrac12\sigma_00.9148440.9924911.002135
qRq_RU1−12σ1U_1-\tfrac12\sigma_11.0221751.0061471.021959
UL, URU_L,\ U_RU0, U1U_0,\ U_10.91484, 1.022180.91484, 1.070140.91484, 1.08943
κ0\kappa_0ν/h\nu/h0.08000.08000.0800
cL, cRc_L,\ c_RqL/2+1, qR/2−1q_L/2+1,\ q_R/2-11.4574, −0.48891.4962, −0.49691.5011, −0.4890
H0H_0Hc+HvH^c+H^v0.3545280.4732630.478379
q˙L\dot q_LU˙0+12σ˙0\dot U_0+\tfrac12\dot\sigma_0−0.425779−0.039237−0.009935
q˙R\dot q_RU˙1−12σ˙1\dot U_1-\tfrac12\dot\sigma_10.1416750.0266290.044071
U˙L, U˙R\dot U_L,\ \dot U_Rv0,0, v0,1v_{0,0},\ v_{0,1}−0.42578, 0.14168−0.42578, 0.34731−0.42578, 0.40591
H˙0\dot H_0cLq˙L+cRq˙R+κ0(U˙L−U˙R)c_L\dot q_L+c_R\dot q_R+\kappa_0(\dot U_L-\dot U_R)−0.735203−0.133787−0.103000
Q˙0\dot Q_0∂Q/∂a\partial Q/\partial a−0.109425−0.109425−0.109425
H˙0−Q˙0\dot H_0-\dot Q_0−0.625779−0.0243620.006425

面 0 是一个普通的面:它的通量由语句 2 从 qL,qR,UL,URq_L,q_R,U_L,U_R 算出,与其他面一样;一阶时 qL=U0q_L=U_0,二阶时 qL=12(U0+U1)q_L=\tfrac12(U_0+U_1)(单侧斜率 σ0=U1−U0\sigma_0=U_1-U_0)。约束行 R0=U0−uinR_0=U_0-u_{\rm in} 使收敛解满足 UL=U0=uinU_L=U_0=u_{\rm in},切线解保持这一点:对每种重构都有 U˙L=U˙0=u˙in=−sin⁡2πφ=−0.4258\dot U_L=\dot U_0=\dot u_{\rm in}=-\sin2\pi\varphi=-0.4258(uinu_{\rm in} 与格式无关)。κ0=ν/h=0.08\kappa_0=\nu/h=0.08 与内部面相同(格心页的边界面上是 ν/(h/2)\nu/(h/2),大一倍)。

Face 0 is an ordinary face: statement 2 computes its flux from qL,qR,UL,URq_L,q_R,U_L,U_R like that of every other face; at first order qL=U0q_L=U_0, at second order qL=12(U0+U1)q_L=\tfrac12(U_0+U_1) (the one-sided slope σ0=U1−U0\sigma_0=U_1-U_0). The constraint row R0=U0−uinR_0=U_0-u_{\rm in} makes the converged state satisfy UL=U0=uinU_L=U_0=u_{\rm in}, and the tangent solution keeps it so: U˙L=U˙0=u˙in=−sin⁡2πφ=−0.4258\dot U_L=\dot U_0=\dot u_{\rm in}=-\sin2\pi\varphi=-0.4258 for every reconstruction (uinu_{\rm in} does not depend on the scheme). κ0=ν/h=0.08\kappa_0=\nu/h=0.08 equals the interior value (on the cell-centred page the boundary face has ν/(h/2)\nu/(h/2), twice as large).

所有面的 H˙f\dot H_f 还给出一个检验。第 5 节的内部行是面值之差,Rj=(Hj−Qj)−(Hj−1−Qj−1)R_j=(H_j-Q_j)-(H_{j-1}-Q_{j-1})(1≤j≤N−11\le j\le N-1),它的切向量也是。当 vkv_k 解出切线方程时,每一行都有 R˙=Avk+RDek=0\dot R=Av_k+R_De_k=0,所以 H˙f−Q˙f\dot H_f-\dot Q_f 在全部 NN 个面上是同一个数:通量切向量跨过对偶控制体 jj 的跳跃恰好等于源项切向量 S˙j=Q˙j−Q˙j−1\dot S_j=\dot Q_j-\dot Q_{j-1},即设计注入这个控制体的量的切向量。这里源项在每个控制体都依赖 aa、φ\varphi、ν\nu,所以 H˙f\dot H_f 每跨过一个控制体都会变,但它与 Q˙f\dot Q_f 之差不变(图 36):无限制器线性重构时,在全部 88 个面上 H˙f−Q˙f=−0.0244\dot H_f-\dot Q_f=-0.0244(aa)、0.25800.2580(φ\varphi)、−0.0165-0.0165(ν\nu),三种重构、三个方向的最大偏差是 1×10−151\times10^{-15}。原始解有同样的结构(第 5 节):收敛时每个面上的 Hf−QfH_f-Q_f 是同一个常数,无限制器线性重构时为 −0.0048-0.0048(一阶 −0.1235-0.1235,光滑限制器 0.00030.0003),离散通量与精确通量只差这一个常数。

The H˙f\dot H_f of all faces make one more check. The interior rows of Section 5 are differences of face values, Rj=(Hj−Qj)−(Hj−1−Qj−1)R_j=(H_j-Q_j)-(H_{j-1}-Q_{j-1}) (1≤j≤N−11\le j\le N-1), and so are their tangents. When vkv_k solves the tangent equation, R˙=Avk+RDek=0\dot R=Av_k+R_De_k=0 in every row, so H˙f−Q˙f\dot H_f-\dot Q_f is the same number on all NN faces: the flux tangent jumps across the dual volume jj by exactly the source tangent S˙j=Q˙j−Q˙j−1\dot S_j=\dot Q_j-\dot Q_{j-1}, the tangent of what the design injects into that volume. Here the source depends on aa, φ\varphi and ν\nu in every volume, so H˙f\dot H_f changes across every volume, but its difference from Q˙f\dot Q_f does not (Figure 36): for the unlimited linear reconstruction H˙f−Q˙f=−0.0244\dot H_f-\dot Q_f=-0.0244 (aa), 0.25800.2580 (φ\varphi) and −0.0165-0.0165 (ν\nu) on all 8 faces, and the largest spread over the three reconstructions and the three directions is 1×10−151\times10^{-15}. The primal has the same structure (Section 5): at the converged state Hf−QfH_f-Q_f is one constant on every face, −0.0048-0.0048 for the unlimited linear reconstruction (−0.1235-0.1235 first order, 0.00030.0003 smooth limiter), the one constant by which the discrete flux misses the exact flux.

图 36 · 切线方程的解使每一行的 R-dot 为零:面通量切向量 H-dot_f(实心点)与精确通量切向量 Q-dot_f(空心圈)逐面变化,它们的差(方块)在全部 8 个面上是同一个常数(默认设计,无限制器线性,种子 (v_k,e_k),k=0,1,2)。三种重构的常数:一阶 (-0.6258, -0.1094, 0.4807),无限制器线性 (-0.0244, 0.2580, -0.0165),光滑限制器 (0.0064, 0.4377, -0.2722)。−2−101200.20.40.60.81xf+1/2​−0.0244a 方向:Ḋ = e0​−2−101200.20.40.60.81xf+1/2​0.2580φ 方向:Ḋ = e1​−2−101200.20.40.60.81xf+1/2​−0.0165ν 方向:Ḋ = e2​Ḣf​Q̇f​Ḣf​ − Q̇f​
图 36 · 切线方程的解使每一行的 R˙\dot R 为零:面通量切向量 H˙f\dot H_f(实心点)与精确通量切向量 Q˙f\dot Q_f(空心圈)逐面变化,它们的差(方块)在全部 8 个面上是同一个常数(默认设计,无限制器线性,种子 (vk,ek)(v_k,e_k),k=0,1,2k=0,1,2)。三种重构的常数:一阶 (−0.6258, −0.1094, 0.4807)(-0.6258,\ -0.1094,\ 0.4807),无限制器线性 (−0.0244, 0.2580, −0.0165)(-0.0244,\ 0.2580,\ -0.0165),光滑限制器 (0.0064, 0.4377, −0.2722)(0.0064,\ 0.4377,\ -0.2722)。
Figure 36 · The tangent solution makes R-dot=0 in every row: the face-flux tangent H-dot_f (dots) and the exact-flux tangent Q-dot_f (rings) change from face to face, and their difference (squares) is one constant on all 8 faces (default design, unlimited linear, seeds (v_k,e_k), k=0,1,2). The constants of the three reconstructions: first order (-0.6258, -0.1094, 0.4807), unlimited linear (-0.0244, 0.2580, -0.0165), smooth limiter (0.0064, 0.4377, -0.2722).−2−101200.20.40.60.81xf+1/2​−0.0244a: Ḋ = e0​−2−101200.20.40.60.81xf+1/2​0.2580φ: Ḋ = e1​−2−101200.20.40.60.81xf+1/2​−0.0165ν: Ḋ = e2​Ḣf​Q̇f​Ḣf​ − Q̇f​
Figure 36 · The tangent solution makes R˙=0\dot R=0 in every row: the face-flux tangent H˙f\dot H_f (dots) and the exact-flux tangent Q˙f\dot Q_f (rings) change from face to face, and their difference (squares) is one constant on all 8 faces (default design, unlimited linear, seeds (vk,ek)(v_k,e_k), k=0,1,2k=0,1,2). The constants of the three reconstructions: first order (−0.6258, −0.1094, 0.4807)(-0.6258,\ -0.1094,\ 0.4807), unlimited linear (−0.0244, 0.2580, −0.0165)(-0.0244,\ 0.2580,\ -0.0165), smooth limiter (0.0064, 0.4377, −0.2722)(0.0064,\ 0.4377,\ -0.2722).

约束行的切向量

The constraint rows differentiated

语句 5 是 aa 和 φ\varphi 与状态相遇的唯一地方:R˙0=U˙0−u˙in\dot R_0=\dot U_0-\dot u_{\rm in},R˙N=U˙N−u˙out\dot R_N=\dot U_N-\dot u_{\rm out}。AA 的第 0 行是 (1,0,…,0)(1,0,\dots,0),第 NN 行是 (0,…,0,1)(0,\dots,0,1)(面循环从不写这两行);RDR_D 的第 0 行与第 NN 行相同(u∗u^* 以 1 为周期,uoutu_{\rm out} 的偏导数与 uinu_{\rm in} 的相同):

Statement 5 is the only place where aa and φ\varphi meet the state: R˙0=U˙0−u˙in\dot R_0=\dot U_0-\dot u_{\rm in} and R˙N=U˙N−u˙out\dot R_N=\dot U_N-\dot u_{\rm out}. Row 0 of AA is (1,0,…,0)(1,0,\dots,0) and row NN is (0,…,0,1)(0,\dots,0,1) (the face loop never writes these rows); rows 0 and NN of RDR_D are equal (u∗u^* has period 1, so uoutu_{\rm out} has the same partial derivatives as uinu_{\rm in}):

−∂uin∂D=(sin⁡2πφ, 2πa cos⁡2πφ, 0)=(0.4258, 1.1370, 0).-\frac{\partial u_{\rm in}}{\partial D}=\big(\sin2\pi\varphi,\ 2\pi a\,\cos2\pi\varphi,\ 0\big)=\big(0.4258,\ 1.1370,\ 0\big).

所以这两行里切线方程 Avk=−RDekAv_k=-R_De_k 的解是 vk,0=vk,N=u˙inv_{k,0}=v_{k,N}=\dot u_{\rm in}:对振幅是 −sin⁡2πφ=−0.4258-\sin2\pi\varphi=-0.4258,对相位是 −2πa cos⁡2πφ=−1.1370-2\pi a\,\cos2\pi\varphi=-1.1370,对黏性是 0。单位行使这些端点值精确成立,面循环与源项只决定中间节点的切向量。

In these two rows the solution of the tangent equation Avk=−RDekAv_k=-R_De_k is therefore vk,0=vk,N=u˙inv_{k,0}=v_{k,N}=\dot u_{\rm in}: −sin⁡2πφ=−0.4258-\sin2\pi\varphi=-0.4258 for the amplitude, −2πa cos⁡2πφ=−1.1370-2\pi a\,\cos2\pi\varphi=-1.1370 for the phase and 0 for the viscosity. The unit rows make these end values exact; the face loop and the source decide only the tangents of the nodes in between.

图 37 把本页与格心页 RDR_D 的三列并排画出(N=8N=8,无限制器线性,默认设计)。内部行上两份代码减去的是同一个精确通量:本页是对偶控制体上的 −(Q˙j−Q˙j−1)-(\dot Q_j-\dot Q_{j-1}),格心页是单元上的 −(Q˙i+1−Q˙i)-(\dot Q_{i+1}-\dot Q_i),宽度都是 hh。差别在两端:本页是单位尺度的约束行 −∂uin/∂D-\partial u_{\rm in}/\partial D,第 0 行是 (0.4258, 1.1370, 0.0000)(0.4258,\ 1.1370,\ 0.0000);格心页的端单元行是含边界通量的平衡行,边界值经边界面的系数(含 ν/(h/2)\nu/(h/2))进入,第 0 行是 (−0.0603, 2.1217, 1.1819)(-0.0603,\ 2.1217,\ 1.1819)。

Figure 37 draws the three columns of RDR_D of this page and of the cell-centred page side by side (N=8N=8, unlimited linear, default design). In the interior rows the two codes subtract the same exact fluxes: −(Q˙j−Q˙j−1)-(\dot Q_j-\dot Q_{j-1}) over a dual volume here, −(Q˙i+1−Q˙i)-(\dot Q_{i+1}-\dot Q_i) over a cell there, both of width hh. The two ends differ: this page has the unit-scaled constraint rows −∂uin/∂D-\partial u_{\rm in}/\partial D, whose row 0 is (0.4258, 1.1370, 0.0000)(0.4258,\ 1.1370,\ 0.0000); the cell page has end-cell balance rows that contain the boundary flux, the boundary data entering through the coefficients of the boundary face (with ν/(h/2)\nu/(h/2)), and its row 0 is (−0.0603, 2.1217, 1.1819)(-0.0603,\ 2.1217,\ 1.1819).

图 37 · R_D 的三列,本页与格心页(N=8,无限制器线性,默认设计)。横轴是行的位置(对偶控制体的中心 x_j,单元的中心 x_i)。绿点:本页的内部行 1,…,N-1;紫色方块:本页的两个约束行(x=0 与 x=1 处);橙色空心圈与虚线:格心页的 N 个单元行。内部行是同样宽度上的同一精确源项的切向量;两端的行性质不同,所以数值也不同。−101200.20.40.60.81xa 方向:Ḋ = e0​−101200.20.40.60.81xφ 方向:Ḋ = e1​−101200.20.40.60.81xν 方向:Ḋ = e2​本页:内部行(对偶控制体)本页:两个约束行格心页:单元行
图 37 · RDR_D 的三列,本页与格心页(N=8N=8,无限制器线性,默认设计)。横轴是行的位置(对偶控制体的中心 xjx_j,单元的中心 xix_i)。绿点:本页的内部行 1,…,N−11,\dots,N-1;紫色方块:本页的两个约束行(x=0x=0 与 x=1x=1 处);橙色空心圈与虚线:格心页的 NN 个单元行。内部行是同样宽度上的同一精确源项的切向量;两端的行性质不同,所以数值也不同。
Figure 37 · The three columns of R_D, this page and the cell-centred page (N=8, unlimited linear, default design). The horizontal axis is the position of the row (the centre x_j of a dual volume, the centre x_i of a cell). Green dots: the interior rows 1,…,N-1 of this page; violet squares: its two constraint rows (at x=0 and x=1); orange rings and dashes: the N cell rows of the cell page. The interior rows are the tangent of the same exact source over intervals of the same width; the rows at the two ends are of a different kind, so their values differ.−101200.20.40.60.81xa: Ḋ = e0​−101200.20.40.60.81xφ: Ḋ = e1​−101200.20.40.60.81xν: Ḋ = e2​this page: interior rows (dual volumes)this page: the two constraint rowscell page: cell rows
Figure 37 · The three columns of RDR_D, this page and the cell-centred page (N=8N=8, unlimited linear, default design). The horizontal axis is the position of the row (the centre xjx_j of a dual volume, the centre xix_i of a cell). Green dots: the interior rows 1,…,N−11,\dots,N-1 of this page; violet squares: its two constraint rows (at x=0x=0 and x=1x=1); orange rings and dashes: the NN cell rows of the cell page. The interior rows are the tangent of the same exact source over intervals of the same width; the rows at the two ends are of a different kind, so their values differ.

前向导数与有限差分

The tangent against finite differences

前向导数精确到舍入误差;残差的差商则不然。步长为 τ\tau 时的单侧差商与中心差商是

The tangent is exact up to rounding; a finite-difference quotient of the residual is not. The forward and the central quotient with a step τ\tau are

FDτ+=R(𝐔+τ𝐔˙,D+τD˙)−R(𝐔,D)τ,FDτc=R(𝐔+τ𝐔˙,D+τD˙)−R(𝐔−τ𝐔˙,D−τD˙)2τ.\mathrm{FD}_\tau^+=\frac{R(\mathbf U+\tau\dot{\mathbf U},D+\tau\dot D)-R(\mathbf U,D)}{\tau},\qquad \mathrm{FD}_\tau^{\rm c}=\frac{R(\mathbf U+\tau\dot{\mathbf U},D+\tau\dot D)-R(\mathbf U-\tau\dot{\mathbf U},D-\tau\dot D)}{2\tau}.

FDτ+\mathrm{FD}_\tau^+ 的截断误差是 O(τ)O(\tau),FDτc\mathrm{FD}_\tau^{\rm c} 的是 O(τ2)O(\tau^2);两者都还有约 εmachM/τ\varepsilon_{\rm mach}M/\tau 的舍入误差(εmach\varepsilon_{\rm mach} 是机器精度,不是第 3 节限制器的常数 ϵ\epsilon),其中 M≈max⁡f(∣Hf∣,∣Qf∣)M\approx\max_f(|H_f|,|Q_f|)(这里约 0.720.72;这个 MM 是量级,不是附录 A 的配点数)是残差中相加各项的大小;这个舍入误差即使在 RR 本身为零时(收敛状态正是如此)也不会变小。所以误差随 τ\tau 的双对数图一般呈 V 形:右支是截断,左支是舍入,没有一个 τ\tau 能达到前向导数的精度。

FDτ+\mathrm{FD}_\tau^+ has a truncation error O(τ)O(\tau), FDτc\mathrm{FD}_\tau^{\rm c} one of O(τ2)O(\tau^2), and both carry a rounding error of about εmachM/τ\varepsilon_{\rm mach}M/\tau (εmach\varepsilon_{\rm mach} is the machine epsilon, not the limiter constant ϵ\epsilon of Section 3), where M≈max⁡f(∣Hf∣,∣Qf∣)M\approx\max_f(|H_f|,|Q_f|) (about 0.720.72 here; this MM is a size, not the number of collocation points of Appendix A) is the size of the terms summed into a residual; it does not shrink when RR itself is zero, as at the converged state. So the error against τ\tau is in general a V in a log-log plot: truncation on the right, rounding on the left, and no τ\tau reaches the tangent's accuracy.

本页的残差有一个特殊结构,实验会显示出来。一阶或无限制器线性重构时,通量是迹的二次式,迹是 𝐔\mathbf U 的线性式,uinu_{\rm in} 是 aa 的线性式、QfQ_f 是 aa 的二次式,ν\nu 只以 ν (UR−UL)\nu\,(U_R-U_L) 和 −νux∗-\nu u^*_x 的形式出现:沿 𝐔\mathbf U、aa、ν\nu 中的任何方向,残差都是 τ\tau 的至多二次的多项式。于是 FDτc\mathrm{FD}_\tau^{\rm c} 根本没有截断误差(误差全是舍入,随 τ\tau 增大而减小);只动 ν\nu、只把全部 𝐔\mathbf U 平移同一个常数、或两者同时,残差甚至是线性的(平移使每个面的通量多出同一个 τ2/2\tau^2/2,相邻面的通量之差把它消去),两种差商都没有截断误差。只有含 φ\varphi 的方向(正弦、余弦),或者光滑限制器时改变斜率的状态方向(任何非常数的 𝐔˙\dot{\mathbf U};限制器是 lj,rjl_j,r_j 的有理函数),才让两种差商都出现完整的 V 形;只动 aa 或 ν\nu,或只做常数平移时,光滑限制器的残差仍是二次或线性的,因为斜率不变。实验在当前状态上对 τ=10−1\tau=10^{-1} 到 10−1310^{-13} 计算两种差商,并说明看到的是哪种形状。第 13 节在整个求解上使用这类差商,第 14 节用复数步长去掉舍入那一支。

The residual of this page has a special structure, which the lab shows. With the first-order or the unlimited linear reconstruction the flux is quadratic in the traces, the traces are linear in 𝐔\mathbf U, uinu_{\rm in} is linear and QfQ_f quadratic in aa, and ν\nu enters only as ν (UR−UL)\nu\,(U_R-U_L) and −νux∗-\nu u^*_x: along any direction in 𝐔\mathbf U, aa and ν\nu the residual is a polynomial of degree at most 2 in τ\tau. The central quotient then has no truncation error at all (its error is pure rounding, falling as τ\tau grows), and along ν\nu alone, along a constant shift of all of 𝐔\mathbf U alone, or along both, the residual is even linear (a shift adds the same τ2/2\tau^2/2 to the flux of every face, and the differences of neighbouring fluxes cancel it), so neither quotient has a truncation error. Only a direction containing φ\varphi (sines and cosines), or, with the smooth limiter, a state direction that changes the slopes (any non-constant 𝐔˙\dot{\mathbf U}: the limiter is a rational function of lj,rjl_j,r_j), gives both quotients the full V; along aa or ν\nu alone, or along a constant shift alone, even the smooth-limiter residual stays quadratic or linear, because the slopes do not change. The lab evaluates both quotients for τ\tau from 10−110^{-1} to 10−1310^{-13} on the current state and says which shape it sees. Section 13 uses such quotients on the whole solve, and Section 14 removes the rounding branch with the complex step.

局部导数怎样组成全局 Jacobian

How local derivatives form the global Jacobian

网格固定时,令 zf=(qL,qR,UL,UR,ν)Tz_f=(q_L,q_R,U_L,U_R,\nu)^T 收集面 ff 的通量的五个输入。它们来自这个面读的未知量(集合 𝒮f\mathcal S_f:二阶时内部面 1≤f≤N−21\le f\le N-2 读节点 f−1,…,f+2f-1,\dots,f+2,面 0 与面 N−1N-1 读 3 个节点;一阶时读节点 f,f+1f,f+1)和设计。记 ZfZ_f、KfK_f 为 zfz_f 对这些未知量和对 DD 的导数,Hz,fH_{z,f} 为五个通量导数组成的行,ℬ\mathcal B 为面与行的有向关联矩阵(N+1N+1 行 NN 列:ℬf,f=+1\mathcal B_{f,f}=+1(f≥1f\ge1),ℬf+1,f=−1\mathcal B_{f+1,f}=-1(f≤N−2f\le N-2):面把通量加给左边的对偶控制体、从右边的减去;边界节点的行 0 与行 NN 不由面写入,所以 ℬ\mathcal B 的第一行和最后一行是零)。源项 Sj=Qj−Qj−1S_j=Q_j-Q_{j-1}(1≤j≤N−11\le j\le N-1)用的是同一个关联矩阵,S=ℬQS=\mathcal BQ,再加上两个约束行,所以:

At a fixed mesh, let zf=(qL,qR,UL,UR,ν)Tz_f=(q_L,q_R,U_L,U_R,\nu)^T collect the five inputs of the flux of face ff. They come from the unknowns the face reads (the set 𝒮f\mathcal S_f: at second order the nodes f−1,…,f+2f-1,\dots,f+2 for 1≤f≤N−21\le f\le N-2 and three nodes for f=0f=0 and f=N−1f=N-1; at first order the nodes f,f+1f,f+1) and from the design. Let ZfZ_f and KfK_f be the derivatives of zfz_f with respect to those unknowns and to DD, Hz,fH_{z,f} the row of the five flux derivatives, and ℬ\mathcal B the oriented incidence of faces and rows (N+1N+1 rows, NN columns: ℬf,f=+1\mathcal B_{f,f}=+1 (f≥1f\ge1), ℬf+1,f=−1\mathcal B_{f+1,f}=-1 (f≤N−2f\le N-2): a face adds its flux to the dual volume on its left and subtracts it from the one on its right; the rows 0 and NN of the boundary nodes are not written by the faces, so the first and the last row of ℬ\mathcal B are zero). The source Sj=Qj−Qj−1S_j=Q_j-Q_{j-1} (1≤j≤N−11\le j\le N-1) uses the same incidence, S=ℬQS=\mathcal BQ, and the two constraint rows are added, so that

R=ℬ(H−Q)+e0(U0−uin)+eN(UN−uout).R=\mathcal B(H-Q)+e_0(U_0-u_{\rm in})+e_N(U_N-u_{\rm out}).
Hz,f=∂H∂zf=(cL, cR, κf, −κf, −UR−ULdf),z˙f=Zf 𝒢f𝐔˙+Kf D˙,H˙f=Hz,f z˙f,H_{z,f}=\frac{\partial H}{\partial z_f}=\Big(c_L,\ c_R,\ \kappa_f,\ -\kappa_f,\ -\frac{U_R-U_L}{d_f}\Big),\qquad \dot z_f=Z_f\,\mathcal G_f\dot{\mathbf U}+K_f\,\dot D,\qquad \dot H_f=H_{z,f}\,\dot z_f,
A=∑fℬ:,f Hz,f Zf 𝒢f+e0e0T+eNeNT,RD=∑fℬ:,f Hz,f Kf−ℬ ∂Q∂D−e0∂uin∂D−eN∂uout∂D.A=\sum_f\mathcal B_{:,f}\,H_{z,f}\,Z_f\,\mathcal G_f+e_0e_0^T+e_Ne_N^T,\qquad R_D=\sum_f\mathcal B_{:,f}\,H_{z,f}\,K_f-\mathcal B\,\frac{\partial Q}{\partial D}-e_0\frac{\partial u_{\rm in}}{\partial D}-e_N\frac{\partial u_{\rm out}}{\partial D}.

AA 里没有 −∂S/∂𝐔-\partial S/\partial\mathbf U 一项:本页的源项只依赖设计;除了面的和,AA 只多出两个约束行的单位元。KfK_f 在每个面上(边界面也一样)只有一行非零,即 ν\nu 那一行 (0,0,1)(0,0,1),所以 Hz,fKf=(0,0,−(UR−UL)/df)H_{z,f}K_f=(0,0,-(U_R-U_L)/d_f)。设计的三条路径就是三项:每个面上的 −(UR−UL)/df-(U_R-U_L)/d_f 乘 ν˙\dot\nu,每个内部行的 −∂S/∂D-\partial S/\partial D,以及两个约束行里的 −∂uin/∂D-\partial u_{\rm in}/\partial D、−∂uout/∂D-\partial u_{\rm out}/\partial D。图 38 画出 AA 的和式中的一项。

There is no −∂S/∂𝐔-\partial S/\partial\mathbf U term in AA: the source of this page depends on the design only; besides the sum over the faces, AA gets only the unit entries of the two constraint rows. KfK_f has one nonzero row on every face, boundary faces included, the ν\nu-row (0,0,1)(0,0,1), so Hz,fKf=(0,0,−(UR−UL)/df)H_{z,f}K_f=(0,0,-(U_R-U_L)/d_f). The three paths of the design are three terms: −(UR−UL)/df-(U_R-U_L)/d_f times ν˙\dot\nu on every face, −∂S/∂D-\partial S/\partial D in every interior row, and −∂uin/∂D-\partial u_{\rm in}/\partial D, −∂uout/∂D-\partial u_{\rm out}/\partial D in the two constraint rows. Figure 38 draws one term of the sum for AA.

图 38 · 面 f=3 对 A 的贡献 A_3= B_(:,3)H_(z,3)Z_3 G_3(默认设计,无限制器线性)。上:四个初等 Jacobian 及其形状。G_3 从 9 个未知量中取出 U_2,…,U_5;Z_3 是迹和未重构状态对它们的导数(ν 那一行为零);H_(z,3) 是五个通量导数;B_(:,3) 把结果以 +1、-1 写入第 3、4 行。下:乘积是一个只有 2 × 4 块非零的 9 × 9 矩阵(左);右边的 A 是 8 个面之和加上两个约束行的单位元,框出的块等于 A_3 的块加上相邻面写入同两行的贡献。面 f = 3 对 A 的贡献:A3​ = B:,3​ Hz,3​ Z3​ G3​(默认设计,无限制器线性)1−1B:,3​9×11.569−0.4400.080−0.0800.865Hz,3​1×5cL​cR​κf​−κf​−(UR​−UL​)/df​−0.2510.25000.251−0.25010000100000Z3​5×4qL​qR​UL​UR​νU2​U3​U4​U5​G3​4×91111= A3​(9×9,只有 2×4 块非零)−0.41.5−0.10.10.4−1.50.1−0.1012345678012345678A = Σf​ Af​ + 两个约束行(框出的是面 3 的块)1.0−1.11.4−0.20.10.4−1.91.7−0.20.10.4−2.01.6−0.20.10.4−1.91.6−0.30.10.4−1.81.6−0.40.10.4−1.71.6−0.50.10.4−1.71.6−0.21.0012345678012345678+ …
图 38 · 面 f=3f=3 对 AA 的贡献 A3=ℬ:,3Hz,3Z3𝒢3A_3=\mathcal B_{:,3}H_{z,3}Z_3\mathcal G_3(默认设计,无限制器线性)。上:四个初等 Jacobian 及其形状。𝒢3\mathcal G_3 从 9 个未知量中取出 U2,…,U5U_2,\dots,U_5;Z3Z_3 是迹和未重构状态对它们的导数(ν\nu 那一行为零);Hz,3H_{z,3} 是五个通量导数;ℬ:,3\mathcal B_{:,3} 把结果以 +1+1、−1-1 写入第 3、4 行。下:乘积是一个只有 2×42\times4 块非零的 9×99\times9 矩阵(左);右边的 AA 是 8 个面之和加上两个约束行的单位元,框出的块等于 A3A_3 的块加上相邻面写入同两行的贡献。
Figure 38 · The contribution of face f=3 to A, A_3= B_(:,3)H_(z,3)Z_3 G_3 (default design, unlimited linear). Top: the four elementary Jacobians and their shapes. G_3 picks U_2,…,U_5 out of the 9 unknowns; Z_3 holds the derivatives of the traces and the raw states with respect to them (the ν-row is zero); H_(z,3) the five flux derivatives; B_(:,3) writes the result into rows 3 and 4 with +1 and -1. Bottom: the product is a 9 × 9 matrix with one nonzero 2 × 4 block (left); the matrix A (right) is the sum over the 8 faces plus the unit entries of the two constraint rows, and its framed block equals the block of A_3 plus the contributions of the neighbouring faces to the same two rows.The contribution of face f = 3 to A: A3​ = B:,3​ Hz,3​ Z3​ G3​ (default design, unlimited linear)1−1B:,3​9×11.569−0.4400.080−0.0800.865Hz,3​1×5cL​cR​κf​−κf​−(UR​−UL​)/df​−0.2510.25000.251−0.25010000100000Z3​5×4qL​qR​UL​UR​νU2​U3​U4​U5​G3​4×91111= A3​ (9×9, a 2×4 nonzero block)−0.41.5−0.10.10.4−1.50.1−0.1012345678012345678A = Σf​ Af​ + the two constraint rows (framed: the block of face 3)1.0−1.11.4−0.20.10.4−1.91.7−0.20.10.4−2.01.6−0.20.10.4−1.91.6−0.30.10.4−1.81.6−0.40.10.4−1.71.6−0.50.10.4−1.71.6−0.21.0012345678012345678+ …
Figure 38 · The contribution of face f=3f=3 to AA, A3=ℬ:,3Hz,3Z3𝒢3A_3=\mathcal B_{:,3}H_{z,3}Z_3\mathcal G_3 (default design, unlimited linear). Top: the four elementary Jacobians and their shapes. 𝒢3\mathcal G_3 picks U2,…,U5U_2,\dots,U_5 out of the 9 unknowns; Z3Z_3 holds the derivatives of the traces and the raw states with respect to them (the ν\nu-row is zero); Hz,3H_{z,3} the five flux derivatives; ℬ:,3\mathcal B_{:,3} writes the result into rows 3 and 4 with +1+1 and −1-1. Bottom: the product is a 9×99\times9 matrix with one nonzero 2×42\times4 block (left); the matrix AA (right) is the sum over the 8 faces plus the unit entries of the two constraint rows, and its framed block equals the block of A3A_3 plus the contributions of the neighbouring faces to the same two rows.

从程序到前向导数:逐条线性化面循环的四步

From program to tangent: linearise the four steps of the face loop

上面的 z˙f\dot z_f、H˙f\dot H_f、R˙\dot R 来自一段短程序:面循环在每个面上做四件事(语句 1c、2、3 以及它们读的斜率)。把这个面读的未知量排成 𝐮f\mathbf u_f:

The z˙f\dot z_f, H˙f\dot H_f and R˙\dot R above come from one short program: on every face the loop does four things (statements 1c, 2 and 3 and the slopes they read). Stack the unknowns the face reads as 𝐮f\mathbf u_f:

(1) 𝐮f=𝒢f𝐔,(2) zf=zf(𝐮f,D),(3) Hf=H(zf),(4) R+=ℬ:,fHf.(1)\ \mathbf u_f=\mathcal G_f\mathbf U,\qquad (2)\ z_f=z_f(\mathbf u_f,D),\qquad (3)\ H_f=H(z_f),\qquad (4)\ R\mathrel{\text{+=}}\mathcal B_{:,f}H_f.

(1)取值:𝒢f\mathcal G_f 的每一行只有一个 1,从全局数组中取出 𝒮f\mathcal S_f 的一个未知量。(2)重构:斜率、迹 qL,qRq_L,q_R、未重构状态 UL,URU_L,U_R 和黏性,即通量的全部五个输入。(3)通量。(4)分发:ℬ\mathcal B 的第 ff 列,第 ff 行为 +1+1,第 f+1f+1 行为 −1-1(边界节点的行除外)。前向模式对每条语句用一次链式法则,每个中间变量都有自己的切向量:

(1) Gather: each row of 𝒢f\mathcal G_f holds a single 1 and picks one unknown of 𝒮f\mathcal S_f out of the global array. (2) Reconstruct: the slopes, the traces qL,qRq_L,q_R, the raw states UL,URU_L,U_R and the viscosity, all five inputs of the flux. (3) Flux. (4) Scatter: column ff of ℬ\mathcal B, +1+1 in row ff and −1-1 in row f+1f+1 (except in the rows of the boundary nodes). Forward mode applies the chain rule once per statement, and every intermediate variable gets a tangent of its own:

(1) 𝐮˙f=𝒢f𝐔˙,(2) z˙f=Zf𝐮˙f+KfD˙,(3) H˙f=Hz,fz˙f,(4) R˙+=ℬ:,fH˙f.(1)\ \dot{\mathbf u}_f=\mathcal G_f\dot{\mathbf U},\qquad (2)\ \dot z_f=Z_f\dot{\mathbf u}_f+K_f\dot D,\qquad (3)\ \dot H_f=H_{z,f}\dot z_f,\qquad (4)\ \dot R\mathrel{\text{+=}}\mathcal B_{:,f}\dot H_f.

取值和分发是线性的:它们的切向量就是把同样的取值和分发作用在切向量上。只有重构和通量带来依赖当前状态的局部导数(Hz,fH_{z,f} 总是如此,ZfZ_f 只在光滑限制器时如此)。把(1)代入(2)、(2)代入(3)、(3)代入(4),一个面对 AA 的贡献就是四个初等 Jacobian 的乘积,按程序运行的顺序从右向左作用:

Gather and scatter are linear: their tangents are the same gather and scatter applied to the tangents. Only reconstruct and flux bring local derivatives that depend on the current state (ZfZ_f with the smooth limiter, Hz,fH_{z,f} always). Substituting (1) into (2), (2) into (3) and (3) into (4) gives one face's contribution to AA as a product of four elementary Jacobians, applied right to left in the order the program runs:

Af=ℬ:,f Hz,f Zf 𝒢f,Af𝐔˙=ℬ:,f(Hz,f(Zf(𝒢f𝐔˙))).A_f=\mathcal B_{:,f}\,H_{z,f}\,Z_f\,\mathcal G_f,\qquad A_f\dot{\mathbf U}=\mathcal B_{:,f}\Big(H_{z,f}\Big(Z_f\big(\mathcal G_f\dot{\mathbf U}\big)\Big)\Big).

算例:面 3 的前向扫描。设计种子取 D˙=e1\dot D=e_1(相位 φ\varphi),未知量取同一方向的切线解 𝐔˙=v1\dot{\mathbf U}=v_1。φ\varphi 不直接进入任何一个面(每个面上 Kfe1=0K_fe_1=0),所以 H˙3\dot H_3 完全来自状态切向量。数字(默认设计,无限制器线性):

A worked example: the forward sweep of face 3. Seed the design with D˙=e1\dot D=e_1 (the phase φ\varphi) and the unknowns with the tangent solution of the same direction, 𝐔˙=v1\dot{\mathbf U}=v_1. The phase does not enter any face directly (Kfe1=0K_fe_1=0 on every face), so H˙3\dot H_3 comes entirely from the state tangents. The numbers (default design, unlimited linear):

语句Statement量Quantity原始值Primal value切向量Tangent
(1)取值(1) gatherU2U_{2}1.17081−0.21066
U3U_{3}1.165560.72421
U4U_{4}1.057391.37729
U5U_{5}0.912901.35702
设计种子design seedφ\varphi0.071
(2)重构(2) reconstructqL, qRq_L,\ q_R1.13720, 1.120551.12120, 1.21908
UL, URU_L,\ U_R1.16556, 1.057390.72421, 1.37729
ν\nu0.010
(3)通量(3) fluxH3H_30.662521.17041
(4)分发(4) scatterR3+=H3R_3\mathrel{\text{+=}}H_30.662521.17041
R4-=H3R_4\mathrel{\text{-=}}H_3−0.66252−1.17041

对所有面、源项行和约束行求和,这些贡献给出 Av1+RDe1=0Av_1+R_De_1=0,这就是切线方程。若取 D˙=e2\dot D=e_2(ν\nu),这个面还会多出 K3e2=(0,0,0,0,1)TK_3e_2=(0,0,0,0,1)^T 带来的 −(UR−UL)/df-(U_R-U_L)/d_f 一项。下面的播放器对任意面、任意方向重放这四步。

Summed over all faces, the source rows and the constraint rows, these contributions give Av1+RDe1=0Av_1+R_De_1=0: the tangent equation. With D˙=e2\dot D=e_2 (ν\nu) this face would get the extra term −(UR−UL)/df-(U_R-U_L)/d_f from K3e2=(0,0,0,0,1)TK_3e_2=(0,0,0,0,1)^T. The player below replays the four steps for any face and any direction.

前向求解用它做什么

What the tangent solve does with it

一次 residual_d 扫描是乘积,不是求解。第 10 节用它解切线方程,求出使 R=0R=0 沿设计方向保持成立的状态切向量 v=𝐔˙v=\dot{\mathbf U}:取种子 D˙=ek\dot D=e_k,解 Av=−RD D˙Av=-R_D\,\dot D,每个设计分量解一次;目标沿这个方向的导数是 J˙h=gTv\dot J_h=g^Tv。上面面表里的 v0v_0 就是这样的解,所以每个 R˙i\dot R_i 都为零(上面检验的九个种子中最大的 ∣R˙i∣|\dot R_i| 是 8.9×10−168.9\times10^{-16})。

A sweep of residual_d is a product, not a solve. Section 10 uses it to solve the tangent equation for the state tangent v=𝐔˙v=\dot{\mathbf U} that keeps R=0R=0 along a design direction: with the seed D˙=ek\dot D=e_k it solves Av=−RD D˙Av=-R_D\,\dot D, one solve per design component; the derivative of the objective along that direction is J˙h=gTv\dot J_h=g^Tv. The v0v_0 of the face tables above was such a solution: that is why every R˙i\dot R_i vanished (the largest ∣R˙i∣|\dot R_i| over the nine seeds of the check above is 8.9×10−168.9\times10^{-16}).

第 9 节Section 9

伴随:把同一个面循环倒过来

Reverse: the adjoint of the same face loop

本节实验:给一个残差一个单位权重 Rˉ=e4\bar R=e_4,运行反向代码后,哪些未知量会收到贡献?三个设计分量里哪些会?先从前向模板预测,再用反向播放器(或后面的“列与行”实验)检查。

Experiment: Put a unit weight on one residual, Rˉ=e4\bar R=e_4, and run the reverse code: which unknowns receive a contribution, and which of the three design components? Predict from the forward stencil, then check with the reverse player (or the row-and-column lab further down).

第 8 节把一个方向 (𝐔˙,D˙)(\dot{\mathbf U},\dot D) 沿残差代码向前推,得到 R˙=A𝐔˙+RDD˙\dot R=A\dot{\mathbf U}+R_D\dot D。本节把一个权重向量 Rˉ\bar R 沿同一段代码向后拉,得到 𝐔ˉ=ATRˉ\bar{\mathbf U}=A^T\bar R 和 Dˉ=RDTRˉ\bar D=R_D^T\bar R:这是反向(伴随)模式。取 Rˉ=ψ\bar R=\psi(第 11 节伴随方程的解)时,一次扫描得到的 Dˉ\bar D 就是整个梯度 dJh/dD\mathrm dJ_h/\mathrm dD。

Section 8 pushed a direction (𝐔˙,D˙)(\dot{\mathbf U},\dot D) forward through the residual code and obtained R˙=A𝐔˙+RDD˙\dot R=A\dot{\mathbf U}+R_D\dot D. This section pulls a weight vector Rˉ\bar R backwards through the same code and obtains 𝐔ˉ=ATRˉ\bar{\mathbf U}=A^T\bar R and Dˉ=RDTRˉ\bar D=R_D^T\bar R: the reverse (adjoint) mode. With Rˉ=ψ\bar R=\psi, the solution of the adjoint equation of Section 11, one sweep gives the whole gradient dJh/dD\mathrm dJ_h/\mathrm dD as Dˉ\bar D.

伴随为什么存在:转置由内积定义

Why the adjoint exists: the transpose is defined by a dot product

线性映射 ℰ\mathcal E 的转置 ℰT\mathcal E^T 就是把它从内积的一边移到另一边的那个映射:对所有 x˙\dot x 和 yˉ\bar y,

A linear map ℰ\mathcal E has a transpose ℰT\mathcal E^T, the map that moves it from one side of a dot product to the other: for all x˙\dot x and yˉ\bar y,

⟨yˉ,ℰx˙⟩=⟨ℰTyˉ,x˙⟩.\langle\bar y,\mathcal E\dot x\rangle=\langle\mathcal E^T\bar y,\dot x\rangle.

把这个定义用到第 8 节的线性映射 (𝐔˙,D˙)↦R˙=A𝐔˙+RDD˙(\dot{\mathbf U},\dot D)\mapsto\dot R=A\dot{\mathbf U}+R_D\dot D 上。这个映射的转置把残差上的权重 Rˉ\bar R 映成输入上的权重 𝐔ˉ=ATRˉ\bar{\mathbf U}=A^T\bar R、Dˉ=RDTRˉ\bar D=R_D^T\bar R,定义式就成了自动微分的对偶恒等式:

Apply this to the linear map of Section 8, (𝐔˙,D˙)↦R˙=A𝐔˙+RDD˙(\dot{\mathbf U},\dot D)\mapsto\dot R=A\dot{\mathbf U}+R_D\dot D. Its transpose maps a weight Rˉ\bar R on the residuals to weights on the inputs, 𝐔ˉ=ATRˉ\bar{\mathbf U}=A^T\bar R and Dˉ=RDTRˉ\bar D=R_D^T\bar R, and the definition becomes the duality identity of AD:

RˉTR˙=RˉT(A𝐔˙+RDD˙)=(ATRˉ)T𝐔˙+(RDTRˉ)TD˙=𝐔ˉT𝐔˙+DˉTD˙.\bar R^T\dot R=\bar R^T\big(A\dot{\mathbf U}+R_D\dot D\big)=\big(A^T\bar R\big)^T\dot{\mathbf U}+\big(R_D^T\bar R\big)^T\dot D=\bar{\mathbf U}^T\dot{\mathbf U}+\bar D^T\dot D.

xˉ\bar x 是加权输出 RˉTR\bar R^TR 对 xx 的灵敏度。反向代码逐句转置程序来计算 𝐔ˉ\bar{\mathbf U} 和 Dˉ\bar D,不形成 AA 或 RDR_D;它的代价是一次残差计算的一个不大的常数倍,与输入的个数无关(在本页的实现中实测约为 1 倍;后面“解出来的伴随,以及它省下的代价”一段末尾的计时实验会在你的浏览器里测量)。这个恒等式就是它的检验(后面的点积检验)。

xˉ\bar x is the sensitivity of the weighted output RˉTR\bar R^TR to xx. The reverse code computes 𝐔ˉ\bar{\mathbf U} and Dˉ\bar D by transposing the program statement by statement, without forming AA or RDR_D; its cost is a small constant multiple of one residual evaluation, independent of the number of inputs (about one for this page's implementation, as measured; the cost lab at the end of “The solved adjoint, and what it saves” measures it in your browser). The identity is its test (the dot test further down).

先转置一个面的局部矩阵

First transpose the local matrix of one face

先不管重构。一个面有五个输入、两个输出:它对残差切向量的贡献 ℬ:,fH˙f\mathcal B_{:,f}\dot H_f 只落在第 ff、f+1f+1 两行,第二行是第一行的相反数(右边的控制体收到 −Hf-H_f);边界面只写其中一行,因为边界节点的行属于约束。这个贡献不是完整的 R˙f,R˙f+1\dot R_f,\dot R_{f+1}:相邻的面也往这两行写。把这个 2×52\times5 局部矩阵的转置作用在两行的权重上,直接得到反向语句:先把两个种子相减,再乘以五个通量导数:

Leave the reconstruction aside for a moment. One face has five inputs and two outputs: its contribution ℬ:,fH˙f\mathcal B_{:,f}\dot H_f to the residual tangent falls on the rows ff and f+1f+1 only, the second the negative of the first (the right volume receives −Hf-H_f); a boundary face writes only one of the two, because the rows of the boundary nodes belong to the constraints. It is not the whole of R˙f,R˙f+1\dot R_f,\dot R_{f+1}: the neighbouring faces write into the same rows. The transpose of this 2×52\times5 local matrix, applied to the weights of the two rows, gives the reverse statements directly: subtract the two seeds, then multiply by the five flux derivatives:

(ℬ:,fH˙f)f, f+1=[1−1]Hz,f z˙f,zˉf=[qˉLqˉRUˉLUˉRνˉ]=Hz,fT[1−1][RˉfRˉf+1]=[cLcRκf−κf−(UR−UL)/df]Hˉf,Hˉf=Rˉf−Rˉf+1.\big(\mathcal B_{:,f}\dot H_f\big)_{f,\,f+1}=\begin{bmatrix}1\\ -1\end{bmatrix}H_{z,f}\,\dot z_f,\qquad \bar z_f=\begin{bmatrix}\bar q_L\\ \bar q_R\\ \bar U_L\\ \bar U_R\\ \bar\nu\end{bmatrix}=H_{z,f}^T\begin{bmatrix}1&-1\end{bmatrix}\begin{bmatrix}\bar R_f\\ \bar R_{f+1}\end{bmatrix}=\begin{bmatrix}c_L\\ c_R\\ \kappa_f\\ -\kappa_f\\ -(U_R-U_L)/d_f\end{bmatrix}\bar H_f,\qquad \bar H_f=\bar R_f-\bar R_{f+1}.

取默认解的面 3,两行的权重用第 11 节伴随解的值 Rˉ3=ψ3=−1.0550\bar R_3=\psi_3=-1.0550、Rˉ4=ψ4=−0.9084\bar R_4=\psi_4=-0.9084,于是 Hˉ3=−0.1466\bar H_3=-0.1466,qˉL=cLHˉ3=−0.2300\bar q_L=c_L\bar H_3=-0.2300,qˉR=0.0645\bar q_R=0.0645,UˉL=−0.0117\bar U_L=-0.0117,UˉR=0.0117\bar U_R=0.0117,νˉ=−0.1269\bar\nu=-0.1269。配上第 8 节手算的切向量(种子 e3e_3:q˙L=1\dot q_L=1,q˙R=14\dot q_R=\tfrac14,U˙L=1\dot U_L=1,U˙R=0\dot U_R=0,ν˙=0\dot\nu=0),恒等式两边在这个面上相等(左边只是面 3 对第 3、4 行的贡献;完整的 R˙3,R˙4\dot R_3,\dot R_4 还含面 2、面 4 的贡献):

Take face 3 of the default solution and, as the weights of its two rows, the values of the adjoint solution of Section 11, Rˉ3=ψ3=−1.0550\bar R_3=\psi_3=-1.0550 and Rˉ4=ψ4=−0.9084\bar R_4=\psi_4=-0.9084: then Hˉ3=−0.1466\bar H_3=-0.1466, qˉL=cLHˉ3=−0.2300\bar q_L=c_L\bar H_3=-0.2300, qˉR=0.0645\bar q_R=0.0645, UˉL=−0.0117\bar U_L=-0.0117, UˉR=0.0117\bar U_R=0.0117 and νˉ=−0.1269\bar\nu=-0.1269. With the hand-worked tangents of Section 8 (seed e3e_3: q˙L=1\dot q_L=1, q˙R=14\dot q_R=\tfrac14, U˙L=1\dot U_L=1, U˙R=0\dot U_R=0, ν˙=0\dot\nu=0) both sides of the identity agree on this face (the left side is face 3's share of rows 3 and 4 only; the full R˙3,R˙4\dot R_3,\dot R_4 also contain the contributions of faces 2 and 4):

RˉT(ℬ:,3H˙3)=Rˉ3H˙3−Rˉ4H˙3=Hˉ3H˙3=−0.225601,qˉLq˙L+qˉRq˙R+UˉLU˙L+UˉRU˙R+νˉν˙=−0.225601.\bar R^T\big(\mathcal B_{:,3}\dot H_3\big)=\bar R_3\dot H_3-\bar R_4\dot H_3=\bar H_3\dot H_3=-0.225601,\qquad \bar q_L\dot q_L+\bar q_R\dot q_R+\bar U_L\dot U_L+\bar U_R\dot U_R+\bar\nu\dot\nu=-0.225601.
图 39 · 同一个面的反向数据流(面 3,种子 R-bar=ψ)。从右到左,把 倒过来:(4′)两个残差权重汇集成 H-bar_3=R-bar_3-R-bar_4;(3′)通量的转置给出五个输入伴随;(2′)重构的转置累加到斜率伴随 σ 和设计伴随 ν;(1′)取值的转置把这个面的份额累加进 U(每个未知量一个数:直接的与经过斜率的之和)。每条箭头都反向,带着与前向图相同的局部导数;带上横线的量是伴随(橙色)。(1′)加回 Ū(2′)重构的转置(3′)通量的转置(4′)取值1111½−½cL​κf​−κf​cR​−(UR​ − UL​)/df​+1−1U2​ = 1.1708Ū2​ += 0.0575U3​ = 1.1656Ū3​ += −0.2256U4​ = 1.0574Ū4​ += 0.0187U5​ = 0.9129Ū5​ += −0.0161σ3​ = −0.0567σ̄3​ += −0.1150σ4​ = −0.1263σ̄4​ += −0.0322σj​ 读 Uj−1​, Uj​, Uj+1​权重 −σl​, σl​ − σr​, σr​qL​ = 1.1372q̄L​ = −0.2300UL​ = 1.1656ŪL​ = −0.0117UR​ = 1.0574ŪR​ = 0.0117qR​ = 1.1206q̄R​ = 0.0645ν = 0.010ν̄ += −0.1269H3​ = 0.6625H̄3​ = −0.1466R̄3​ = −1.0550读入,×(+1)R̄4​ = −0.9084读入,×(−1)H̄3​ = R̄3​ − R̄4​ = −0.1466; q̄L​ = cL​ H̄3​, q̄R​ = cR​ H̄3​, ŪL​ = −ŪR​ = κf​ H̄3​, ν̄ += −(UR​ − UL​)/df​ · H̄3​种子:R̄ = ψ(第 11 节的伴随解);方框里的 Ūj​ 是这一个面的份额(直接的与经过斜率的)
图 39 · 同一个面的反向数据流(面 3,种子 Rˉ=ψ\bar R=\psi)。从右到左,把图 33 倒过来:(4′)两个残差权重汇集成 Hˉ3=Rˉ3−Rˉ4\bar H_3=\bar R_3-\bar R_4;(3′)通量的转置给出五个输入伴随;(2′)重构的转置累加到斜率伴随 σˉ\bar\sigma 和设计伴随 νˉ\bar\nu;(1′)取值的转置把这个面的份额累加进 𝐔ˉ\bar{\mathbf U}(每个未知量一个数:直接的与经过斜率的之和)。每条箭头都反向,带着与前向图相同的局部导数;带上横线的量是伴随(橙色)。
Figure 39 · The reverse data flow of the same face (face 3, seed R-bar=ψ). Right to left, the reverse of : (4′) the two residual weights are gathered into H-bar_3=R-bar_3-R-bar_4, (3′) the transposed flux gives the five input adjoints, (2′) the transposed reconstruction adds into the slope adjoints σ and the design adjoint ν, (1′) the transposed gather adds this face's share into U (one number per unknown: the direct part plus the part through the slopes). Every arrow is reversed and carries the same local derivative as in the forward graph; the barred quantities are adjoints (orange).(1′) add into Ū(2′) reconstruction, transposed(3′) flux, transposed(4′) gather1111½−½cL​κf​−κf​cR​−(UR​ − UL​)/df​+1−1U2​ = 1.1708Ū2​ += 0.0575U3​ = 1.1656Ū3​ += −0.2256U4​ = 1.0574Ū4​ += 0.0187U5​ = 0.9129Ū5​ += −0.0161σ3​ = −0.0567σ̄3​ += −0.1150σ4​ = −0.1263σ̄4​ += −0.0322σj​ reads Uj−1​, Uj​, Uj+1​with −σl​, σl​ − σr​, σr​qL​ = 1.1372q̄L​ = −0.2300UL​ = 1.1656ŪL​ = −0.0117UR​ = 1.0574ŪR​ = 0.0117qR​ = 1.1206q̄R​ = 0.0645ν = 0.010ν̄ += −0.1269H3​ = 0.6625H̄3​ = −0.1466R̄3​ = −1.0550read, ×(+1)R̄4​ = −0.9084read, ×(−1)H̄3​ = R̄3​ − R̄4​ = −0.1466; q̄L​ = cL​ H̄3​, q̄R​ = cR​ H̄3​, ŪL​ = −ŪR​ = κf​ H̄3​, ν̄ += −(UR​ − UL​)/df​ · H̄3​seed: R̄ = ψ (the adjoint solution of Section 11); the Ūj​ in the boxes are this face's share (direct and through the slopes)
Figure 39 · The reverse data flow of the same face (face 3, seed Rˉ=ψ\bar R=\psi). Right to left, the reverse of Figure 33: (4′) the two residual weights are gathered into Hˉ3=Rˉ3−Rˉ4\bar H_3=\bar R_3-\bar R_4, (3′) the transposed flux gives the five input adjoints, (2′) the transposed reconstruction adds into the slope adjoints σˉ\bar\sigma and the design adjoint νˉ\bar\nu, (1′) the transposed gather adds this face's share into 𝐔ˉ\bar{\mathbf U} (one number per unknown: the direct part plus the part through the slopes). Every arrow is reversed and carries the same local derivative as in the forward graph; the barred quantities are adjoints (orange).

逐句倒推:残差代码的反向语句

The residual code reversed statement by statement

下表对第 8 节表中的每条语句写出它的伴随语句 xˉk+=(∂ϕ/∂xk) yˉ\bar x_k\mathrel{\text{+=}}(\partial\phi/\partial x_k)\,\bar y,从最后一条原始语句倒回第一条;在面循环里,面按 f=N−1,…,0f=N-1,\dots,0 倒序处理,每个面里的语句也倒着执行。种子是 Rˉ\bar R,其余伴随量(包括每个面、每个节点上的局部伴随 qˉL,lˉj,…\bar q_L,\bar l_j,\dots)都从零开始:

The table lists, for every statement of the table of Section 8, its adjoint statements xˉk+=(∂ϕ/∂xk) yˉ\bar x_k\mathrel{\text{+=}}(\partial\phi/\partial x_k)\,\bar y, from the last primal statement back to the first; inside the face loop the faces run from f=N−1f=N-1 down to 0 and the statements of each face also run backwards. The seed is Rˉ\bar R; every other adjoint (the local ones of each face and node, qˉL,lˉj,…\bar q_L,\bar l_j,\dots, included) starts at zero:

#原始语句Primal statement伴随语句(倒序执行)Adjoint statements (run in reverse order)写入的伴随量Adjoints written
5uin=u∗(0;D), uout=u∗(1;D);  R0=U0−uin, RN=UN−uoutu_{\rm in}=u^*(0;D),\ u_{\rm out}=u^*(1;D);\ \ R_0=U_0-u_{\rm in},\ R_N=U_N-u_{\rm out}Uˉ0+=Rˉ0\bar U_0\mathrel{\text{+=}}\bar R_0,uˉin-=Rˉ0\bar u_{\rm in}\mathrel{\text{-=}}\bar R_0;UˉN+=RˉN\bar U_N\mathrel{\text{+=}}\bar R_N,uˉout-=RˉN\bar u_{\rm out}\mathrel{\text{-=}}\bar R_N;再 aˉ+=∂uin∂a(uˉin+uˉout)\bar a\mathrel{\text{+=}}\frac{\partial u_{\rm in}}{\partial a}(\bar u_{\rm in}+\bar u_{\rm out}),φˉ+=∂uin∂φ(uˉin+uˉout)\bar\varphi\mathrel{\text{+=}}\frac{\partial u_{\rm in}}{\partial\varphi}(\bar u_{\rm in}+\bar u_{\rm out})Uˉ0+=Rˉ0\bar U_0\mathrel{\text{+=}}\bar R_0, uˉin-=Rˉ0\bar u_{\rm in}\mathrel{\text{-=}}\bar R_0; UˉN+=RˉN\bar U_N\mathrel{\text{+=}}\bar R_N, uˉout-=RˉN\bar u_{\rm out}\mathrel{\text{-=}}\bar R_N; then aˉ+=∂uin∂a(uˉin+uˉout)\bar a\mathrel{\text{+=}}\frac{\partial u_{\rm in}}{\partial a}(\bar u_{\rm in}+\bar u_{\rm out}), φˉ+=∂uin∂φ(uˉin+uˉout)\bar\varphi\mathrel{\text{+=}}\frac{\partial u_{\rm in}}{\partial\varphi}(\bar u_{\rm in}+\bar u_{\rm out})Uˉ0, UˉN, uˉin, uˉout, aˉ, φˉ\bar U_0,\ \bar U_N,\ \bar u_{\rm in},\ \bar u_{\rm out},\ \bar a,\ \bar\varphi
4Qf=q∗(xf+1/2;D);  Rj-=Qj−Qj−1Q_f=q^*(x_{f+1/2};D);\ \ R_j\mathrel{\text{-=}}Q_j-Q_{j-1}Qˉj-=Rˉj\bar Q_j\mathrel{\text{-=}}\bar R_j,Qˉj−1+=Rˉj\bar Q_{j-1}\mathrel{\text{+=}}\bar R_j(j=N−1,…,1j=N-1,\dots,1);再 Dˉ+=(∂Qf∂D)TQˉf\bar D\mathrel{\text{+=}}\big(\frac{\partial Q_f}{\partial D}\big)^T\bar Q_f(f=N−1,…,0f=N-1,\dots,0)Qˉj-=Rˉj\bar Q_j\mathrel{\text{-=}}\bar R_j, Qˉj−1+=Rˉj\bar Q_{j-1}\mathrel{\text{+=}}\bar R_j (j=N−1,…,1j=N-1,\dots,1); then Dˉ+=(∂Qf∂D)TQˉf\bar D\mathrel{\text{+=}}\big(\frac{\partial Q_f}{\partial D}\big)^T\bar Q_f (f=N−1,…,0f=N-1,\dots,0)Qˉf, aˉ, φˉ, νˉ\bar Q_f,\ \bar a,\ \bar\varphi,\ \bar\nu
3Rf+=Hf (f≥1);  Rf+1-=Hf (f≤N−2)R_f\mathrel{\text{+=}}H_f\ (f\ge1);\ \ R_{f+1}\mathrel{\text{-=}}H_f\ (f\le N-2)Hˉf←0\bar H_f\leftarrow0;Hˉf+=Rˉf (f≥1)\bar H_f\mathrel{\text{+=}}\bar R_f\ (f\ge1),Hˉf-=Rˉf+1 (f≤N−2)\bar H_f\mathrel{\text{-=}}\bar R_{f+1}\ (f\le N-2)(面循环 f=N−1,…,0f=N-1,\dots,0)Hˉf←0\bar H_f\leftarrow0; Hˉf+=Rˉf (f≥1)\bar H_f\mathrel{\text{+=}}\bar R_f\ (f\ge1), Hˉf-=Rˉf+1 (f≤N−2)\bar H_f\mathrel{\text{-=}}\bar R_{f+1}\ (f\le N-2) (face loop f=N−1,…,0f=N-1,\dots,0)Hˉf\bar H_f
2Hf=H(qL,qR,UL,UR,ν)H_f=H(q_L,q_R,U_L,U_R,\nu)qˉL+=cLHˉf\bar q_L\mathrel{\text{+=}}c_L\bar H_f,qˉR+=cRHˉf\bar q_R\mathrel{\text{+=}}c_R\bar H_f,UˉL+=κfHˉf\bar U_L\mathrel{\text{+=}}\kappa_f\bar H_f,UˉR+=−κfHˉf\bar U_R\mathrel{\text{+=}}-\kappa_f\bar H_f,νˉ+=−UR−ULdfHˉf\bar\nu\mathrel{\text{+=}}-\frac{U_R-U_L}{d_f}\bar H_fqˉL+=cLHˉf\bar q_L\mathrel{\text{+=}}c_L\bar H_f, qˉR+=cRHˉf\bar q_R\mathrel{\text{+=}}c_R\bar H_f, UˉL+=κfHˉf\bar U_L\mathrel{\text{+=}}\kappa_f\bar H_f, UˉR+=−κfHˉf\bar U_R\mathrel{\text{+=}}-\kappa_f\bar H_f, νˉ+=−UR−ULdfHˉf\bar\nu\mathrel{\text{+=}}-\frac{U_R-U_L}{d_f}\bar H_fqˉL,qˉR,UˉL,UˉR,νˉ\bar q_L,\bar q_R,\bar U_L,\bar U_R,\bar\nu
1cqL=Uf+12σf, UL=Uf;  qR=Uf+1−12σf+1, UR=Uf+1q_L=U_f+\tfrac12\sigma_f,\ U_L=U_f;\ \ q_R=U_{f+1}-\tfrac12\sigma_{f+1},\ U_R=U_{f+1}Uˉf+=qˉL+UˉL\bar U_f\mathrel{\text{+=}}\bar q_L+\bar U_L,σˉf+=12qˉL\bar\sigma_f\mathrel{\text{+=}}\tfrac12\bar q_L;Uˉf+1+=qˉR+UˉR\bar U_{f+1}\mathrel{\text{+=}}\bar q_R+\bar U_R,σˉf+1+=−12qˉR\bar\sigma_{f+1}\mathrel{\text{+=}}-\tfrac12\bar q_RUˉf+=qˉL+UˉL\bar U_f\mathrel{\text{+=}}\bar q_L+\bar U_L, σˉf+=12qˉL\bar\sigma_f\mathrel{\text{+=}}\tfrac12\bar q_L; Uˉf+1+=qˉR+UˉR\bar U_{f+1}\mathrel{\text{+=}}\bar q_R+\bar U_R, σˉf+1+=−12qˉR\bar\sigma_{f+1}\mathrel{\text{+=}}-\tfrac12\bar q_RUˉf, Uˉf+1, σˉf, σˉf+1\bar U_f,\ \bar U_{f+1},\ \bar\sigma_f,\ \bar\sigma_{f+1}
1bσ0=U1−U0\sigma_0=U_1-U_0,σN=UN−UN−1\sigma_N=U_N-U_{N-1};σj=σ(lj,rj)\sigma_j=\sigma(l_j,r_j)σ0=U1−U0\sigma_0=U_1-U_0, σN=UN−UN−1\sigma_N=U_N-U_{N-1}; σj=σ(lj,rj)\sigma_j=\sigma(l_j,r_j)Uˉ1+=σˉ0\bar U_1\mathrel{\text{+=}}\bar\sigma_0,Uˉ0+=−σˉ0\bar U_0\mathrel{\text{+=}}-\bar\sigma_0;UˉN+=σˉN\bar U_N\mathrel{\text{+=}}\bar\sigma_N,UˉN−1+=−σˉN\bar U_{N-1}\mathrel{\text{+=}}-\bar\sigma_N(二阶);lˉj+=σlσˉj\bar l_j\mathrel{\text{+=}}\sigma_l\bar\sigma_j,rˉj+=σrσˉj\bar r_j\mathrel{\text{+=}}\sigma_r\bar\sigma_j(j=N−1,…,1j=N-1,\dots,1,在面循环之后)Uˉ1+=σˉ0\bar U_1\mathrel{\text{+=}}\bar\sigma_0, Uˉ0+=−σˉ0\bar U_0\mathrel{\text{+=}}-\bar\sigma_0; UˉN+=σˉN\bar U_N\mathrel{\text{+=}}\bar\sigma_N, UˉN−1+=−σˉN\bar U_{N-1}\mathrel{\text{+=}}-\bar\sigma_N (second order); lˉj+=σlσˉj\bar l_j\mathrel{\text{+=}}\sigma_l\bar\sigma_j, rˉj+=σrσˉj\bar r_j\mathrel{\text{+=}}\sigma_r\bar\sigma_j (j=N−1,…,1j=N-1,\dots,1, after the face loop)Uˉ0,Uˉ1,UˉN−1,UˉN, lˉj, rˉj\bar U_0,\bar U_1,\bar U_{N-1},\bar U_N,\ \bar l_j,\ \bar r_j
1alj=Uj−Uj−1,  rj=Uj+1−Ujl_j=U_j-U_{j-1},\ \ r_j=U_{j+1}-U_jUˉj+=lˉj−rˉj,  Uˉj−1+=−lˉj,  Uˉj+1+=rˉj\bar U_j\mathrel{\text{+=}}\bar l_j-\bar r_j,\ \ \bar U_{j-1}\mathrel{\text{+=}}-\bar l_j,\ \ \bar U_{j+1}\mathrel{\text{+=}}\bar r_j𝐔ˉ\bar{\mathbf U}
0R←0R\leftarrow0无:Rˉ\bar R 是种子(扫描前 𝐔ˉ←0\bar{\mathbf U}\leftarrow0,Dˉ←0\bar D\leftarrow0)nothing: Rˉ\bar R is the seed (𝐔ˉ←0\bar{\mathbf U}\leftarrow0, Dˉ←0\bar D\leftarrow0 before the sweep)—

有四点值得注意。(i)分发的伴随是取值:语句 3 把一个数写进两行,它的伴随 Hˉf=Rˉf−Rˉf+1\bar H_f=\bar R_f-\bar R_{f+1} 把两行读回一个数(边界面只有一行可读)。(ii)每个输入的伴随都用 += 累加:UjU_j 被几个面读(还经过斜率),σj\sigma_j 被两个面读,设计被每个面和每一行读;链式法则对每次使用给出一项(见下图)。(iii)源项行也由同一个取值倒转:Qˉf=Rˉf+1−Rˉf=−Hˉf\bar Q_f=\bar R_{f+1}-\bar R_f=-\bar H_f(约束行 0 与行 NN 不参与),所以源项给设计伴随的贡献是 −∑fHˉf (∂Qf/∂D)T-\sum_f\bar H_f\,(\partial Q_f/\partial D)^T。(iv)约束行是 Rˉ0,RˉN\bar R_0,\bar R_N 的唯一出口:Uˉ0+=Rˉ0\bar U_0\mathrel{\text{+=}}\bar R_0,uˉin-=Rˉ0\bar u_{\rm in}\mathrel{\text{-=}}\bar R_0,减号来自 R0=U0−uinR_0=U_0-u_{\rm in} 里的 −uin-u_{\rm in};语句 5 用了 ∂uout/∂D=∂uin/∂D\partial u_{\rm out}/\partial D=\partial u_{\rm in}/\partial D(u∗u^* 以 1 为周期)。反向语句要读的原始值(cL,cR,κf,UR−UL,σl,σrc_L,c_R,\kappa_f,U_R-U_L,\sigma_l,\sigma_r)由收敛解 𝐔\mathbf U 重算(或在一次前向扫描中存下)。

Four things to notice. (i) The adjoint of a scatter is a gather: statement 3 wrote one number into two rows, and its adjoint Hˉf=Rˉf−Rˉf+1\bar H_f=\bar R_f-\bar R_{f+1} reads two rows back into one number (a boundary face has only one row to read). (ii) Every input adjoint accumulates with +=: UjU_j is read by several faces (and through the slopes), σj\sigma_j by two faces, the design by every face and every row; the chain rule gives one term per use (the figure below). (iii) The source rows are reversed by the same gather: Qˉf=Rˉf+1−Rˉf=−Hˉf\bar Q_f=\bar R_{f+1}-\bar R_f=-\bar H_f (the constraint rows 0 and NN do not enter), so the source contributes −∑fHˉf (∂Qf/∂D)T-\sum_f\bar H_f\,(\partial Q_f/\partial D)^T to the design adjoint. (iv) The constraint rows are the only exit of Rˉ0,RˉN\bar R_0,\bar R_N: Uˉ0+=Rˉ0\bar U_0\mathrel{\text{+=}}\bar R_0 and uˉin-=Rˉ0\bar u_{\rm in}\mathrel{\text{-=}}\bar R_0, the minus sign coming from the −uin-u_{\rm in} of R0=U0−uinR_0=U_0-u_{\rm in}; statement 5 uses ∂uout/∂D=∂uin/∂D\partial u_{\rm out}/\partial D=\partial u_{\rm in}/\partial D (u∗u^* has period 1). The primal values the reverse statements read (cL,cR,κf,UR−UL,σl,σrc_L,c_R,\kappa_f,U_R-U_L,\sigma_l,\sigma_r) are recomputed from the converged solution 𝐔\mathbf U (or stored by a forward sweep).

写成自动微分工具生成的 residual_b:

As the residual_b an AD tool would generate:

residual_b(U, D, res_b) -> u_b, D_b          # D_b = (a_b, phi_b, nu_b)
    (原始语句 1a-1b 先运行:s[j] 以及斜率的偏导数 sl[j]、sr[j])
 0  u_b = 0;  D_b = 0;  s_b = 0;  Q_b = 0;  uin_b = 0;  uout_b = 0
 5' u_b[0] += res_b[0];   uin_b  -= res_b[0]
    u_b[N] += res_b[N];   uout_b -= res_b[N]
    a_b   += -sin(2 pi phi)*(uin_b + uout_b)
    phi_b += -2 pi a cos(2 pi phi)*(uin_b + uout_b)
    for j = N-1 .. 1:
 4b'  Q_b[j] -= res_b[j];  Q_b[j-1] += res_b[j]
    for f = N-1 .. 0:
 4a'  a_b += dQda(xf[f])*Q_b[f];  phi_b += dQdphi(xf[f])*Q_b[f];  nu_b += dQdnu(xf[f])*Q_b[f]
    for f = N-1 .. 0:
      (重算面 f 的 qL、qR、UL、UR、cL、cR:原始语句 1c 与 2)
 3'   H_b = 0
      if f >= 1:    H_b += res_b[f]
      if f <= N-2:  H_b -= res_b[f+1]
 2'   qL_b = cL*H_b;  qR_b = cR*H_b;  UL_b = nu/h*H_b;  UR_b = -nu/h*H_b
      nu_b += -(UR - UL)/h*H_b
 1c'  u_b[f]   += qL_b + UL_b;  s_b[f]   += qL_b/2
      u_b[f+1] += qR_b + UR_b;  s_b[f+1] -= qR_b/2
 1b'  u_b[1] += s_b[0];  u_b[0] -= s_b[0]            (二阶:两个端点节点)
      u_b[N] += s_b[N];  u_b[N-1] -= s_b[N]
    for j = N-1 .. 1:
 1b'  l_b = sl[j]*s_b[j];  r_b = sr[j]*s_b[j]
 1a'  u_b[j] += l_b - r_b;  u_b[j-1] -= l_b;  u_b[j+1] += r_b
residual_b(U, D, res_b) -> u_b, D_b          # D_b = (a_b, phi_b, nu_b)
    (the primal statements 1a-1b run first: s[j] and the slope partials sl[j], sr[j])
 0  u_b = 0;  D_b = 0;  s_b = 0;  Q_b = 0;  uin_b = 0;  uout_b = 0
 5' u_b[0] += res_b[0];   uin_b  -= res_b[0]
    u_b[N] += res_b[N];   uout_b -= res_b[N]
    a_b   += -sin(2 pi phi)*(uin_b + uout_b)
    phi_b += -2 pi a cos(2 pi phi)*(uin_b + uout_b)
    for j = N-1 .. 1:
 4b'  Q_b[j] -= res_b[j];  Q_b[j-1] += res_b[j]
    for f = N-1 .. 0:
 4a'  a_b += dQda(xf[f])*Q_b[f];  phi_b += dQdphi(xf[f])*Q_b[f];  nu_b += dQdnu(xf[f])*Q_b[f]
    for f = N-1 .. 0:
      (recompute qL, qR, UL, UR, cL, cR of face f: statements 1c and 2 of the primal)
 3'   H_b = 0
      if f >= 1:    H_b += res_b[f]
      if f <= N-2:  H_b -= res_b[f+1]
 2'   qL_b = cL*H_b;  qR_b = cR*H_b;  UL_b = nu/h*H_b;  UR_b = -nu/h*H_b
      nu_b += -(UR - UL)/h*H_b
 1c'  u_b[f]   += qL_b + UL_b;  s_b[f]   += qL_b/2
      u_b[f+1] += qR_b + UR_b;  s_b[f+1] -= qR_b/2
 1b'  u_b[1] += s_b[0];  u_b[0] -= s_b[0]            (second order: the end nodes)
      u_b[N] += s_b[N];  u_b[N-1] -= s_b[N]
    for j = N-1 .. 1:
 1b'  l_b = sl[j]*s_b[j];  r_b = sr[j]*s_b[j]
 1a'  u_b[j] += l_b - r_b;  u_b[j-1] -= l_b;  u_b[j+1] += r_b

约束行的反向语句

The constraint rows reversed

语句 5 是反向代码最先遇到的语句。以 Rˉ=ψ\bar R=\psi 为种子:Uˉ0+=ψ0\bar U_0\mathrel{\text{+=}}\psi_0,uˉin-=ψ0\bar u_{\rm in}\mathrel{\text{-=}}\psi_0,节点 NN 同理(ψ0,ψN\psi_0,\psi_N 是两个约束行的乘子,默认解里 ψ0=−1.4061\psi_0=-1.4061,ψN=−0.0870\psi_N=-0.0870)。于是 uˉin=−ψ0=1.4061\bar u_{\rm in}=-\psi_0=1.4061,uˉout=−ψN=0.0870\bar u_{\rm out}=-\psi_N=0.0870,再经 ∂uin/∂D\partial u_{\rm in}/\partial D 给设计伴随最先的两项:aˉ=−sin⁡2πφ (uˉin+uˉout)=−0.6357\bar a=-\sin2\pi\varphi\,(\bar u_{\rm in}+\bar u_{\rm out})=-0.6357,φˉ=−2πa cos⁡2πφ (uˉin+uˉout)=−1.6977\bar\varphi=-2\pi a\,\cos2\pi\varphi\,(\bar u_{\rm in}+\bar u_{\rm out})=-1.6977。源项(语句 4′)和面通量里的黏性(语句 2′)补上其余部分;下表按语句拆开最终的 Dˉ=dJh/dD\bar D=\mathrm dJ_h/\mathrm dD(无限制器线性,默认设计)。与前向对照:前向代码里 u˙in\dot u_{\rm in} 流进 R˙0\dot R_0,反向代码里 Rˉ0\bar R_0 经 uˉin\bar u_{\rm in} 流向设计。

Statement 5 is the first statement the reverse code meets. With the seed Rˉ=ψ\bar R=\psi: Uˉ0+=ψ0\bar U_0\mathrel{\text{+=}}\psi_0 and uˉin-=ψ0\bar u_{\rm in}\mathrel{\text{-=}}\psi_0, and likewise at node NN (ψ0\psi_0 and ψN\psi_N are the multipliers of the two constraint rows; at the default solution ψ0=−1.4061\psi_0=-1.4061 and ψN=−0.0870\psi_N=-0.0870). So uˉin=−ψ0=1.4061\bar u_{\rm in}=-\psi_0=1.4061 and uˉout=−ψN=0.0870\bar u_{\rm out}=-\psi_N=0.0870, and through ∂uin/∂D\partial u_{\rm in}/\partial D they give the design adjoint its first two terms, aˉ=−sin⁡2πφ (uˉin+uˉout)=−0.6357\bar a=-\sin2\pi\varphi\,(\bar u_{\rm in}+\bar u_{\rm out})=-0.6357 and φˉ=−2πa cos⁡2πφ (uˉin+uˉout)=−1.6977\bar\varphi=-2\pi a\,\cos2\pi\varphi\,(\bar u_{\rm in}+\bar u_{\rm out})=-1.6977. The source (statement 4′) and the viscous term of the face fluxes (statement 2′) add the rest; the table splits the final Dˉ=dJh/dD\bar D=\mathrm dJ_h/\mathrm dD by statement (unlimited linear, default design). Compare with the forward code: there u˙in\dot u_{\rm in} flows into R˙0\dot R_0, here Rˉ0\bar R_0 flows through uˉin\bar u_{\rm in} into the design.

#加到 D̄ 的语句Statement that adds to D̄aˉ\bar aφˉ\bar\varphiνˉ\bar\nu
5′边界值 uin(D),uout(D)u_{\rm in}(D),u_{\rm out}(D)(经约束行)the boundary data uin(D),uout(D)u_{\rm in}(D),u_{\rm out}(D) (through the constraint rows)−0.635725−1.6976980.000000
4′精确通量 Qf(D)Q_f(D)(经源项)the exact fluxes Qf(D)Q_f(D) (through the source)0.4576642.1176022.180107
2′面通量里的黏性 ν\nuthe viscosity ν\nu of the face fluxes0.0000000.000000−2.176198
合计sumDˉ=dJh/dD\bar D=\mathrm dJ_h/\mathrm dD−0.1780610.4199040.003909

三部分符号不同,部分抵消:默认解中仅数据语句给 aˉ=−0.636\bar a=-0.636,源项给 0.4580.458,合起来是 −0.178-0.178;对 ν\nu,源项(2.1802.180)与面通量(−2.176-2.176)几乎抵消,剩 0.00390.0039。第 12 节按设计进入残差的位置进一步拆分梯度。

The three parts have different signs and partly cancel: at the default solution the data statement alone gives aˉ=−0.636\bar a=-0.636, the source 0.4580.458, together −0.178-0.178; for ν\nu the source (2.1802.180) and the face fluxes (−2.176-2.176) nearly cancel and leave 0.00390.0039. Section 12 splits the gradient further by the places where the design enters the residual.

约束行的乘子本身也有含义:随着 NN 增大,ψ0,ψN\psi_0,\psi_N 趋向连续伴随 λ\lambda(附录 A)在两端的边界通量 νλx(0)=−1.4266\nu\lambda_x(0)=-1.4266 与 −νλx(1)=−0.0220-\nu\lambda_x(1)=-0.0220;独立的 Python 运行给出 N=32N=32 时 ψ0=−1.4136\psi_0=-1.4136、ψN=−0.0352\psi_N=-0.0352,N=16384N=16384 时 ψ0=−1.4266\psi_0=-1.4266、ψN=−0.0220\psi_N=-0.0220。这是数值观察,不是定理。

The multipliers of the constraint rows have a meaning of their own: as NN grows, ψ0\psi_0 and ψN\psi_N approach the boundary fluxes νλx(0)=−1.4266\nu\lambda_x(0)=-1.4266 and −νλx(1)=−0.0220-\nu\lambda_x(1)=-0.0220 of the continuous adjoint λ\lambda (Appendix A); the independent Python runs give ψ0=−1.4136\psi_0=-1.4136 and ψN=−0.0352\psi_N=-0.0352 at N=32N=32, and ψ0=−1.4266\psi_0=-1.4266 and ψN=−0.0220\psi_N=-0.0220 at N=16384N=16384. This is a numerical observation, not a theorem.

为什么用 +=:程序的扇出就是反向代码的扇入

Why +=: a fan-out of the program is a fan-in of the reverse code

二阶时,内部节点 UjU_j(2≤j≤N−22\le j\le N-2)被四个面读:作为面 j−1j-1 的右状态和面 jj 的左状态,此外还通过斜率 σj−1,σj+1\sigma_{j-1},\sigma_{j+1} 被面 j−2j-2 和面 j+1j+1 读(四个面里共 6 个迹、2 个未重构状态);U1,UN−1U_1,U_{N-1} 被三个面读,边界节点 U0,UNU_0,U_N 被两个面读,并且还出现在自己的约束行里;一阶时每个内部节点被两个面读,边界节点被一个面读。链式法则对每次使用给出一项,所以 Uˉj\bar U_j 是一个和;每条反向语句必须把自己的项加上去(+=),而不是覆盖前面的项:

At second order an interior unknown UjU_j (2≤j≤N−22\le j\le N-2) is read by four faces: as the right state of face j−1j-1 and the left state of face jj, and through the slopes σj−1,σj+1\sigma_{j-1},\sigma_{j+1} by the faces j−2j-2 and j+1j+1 as well (six traces and two raw states in all); U1U_1 and UN−1U_{N-1} are read by three faces, the boundary nodes U0U_0 and UNU_N by two faces and, besides, by their own constraint row; at first order every interior node is read by two faces and a boundary node by one. The chain rule gives one term per use, so Uˉj\bar U_j is a sum, and every reverse statement must add its term (+=) instead of overwriting the earlier ones:

Uˉj=∑f: j∈𝒮f∂Hf∂Uj Hˉf  (1≤j≤N−1),Uˉj=Rˉj+∑f: j∈𝒮f∂Hf∂Uj Hˉf  (j=0,N).\bar U_j=\sum_{f:\ j\in\mathcal S_f}\frac{\partial H_f}{\partial U_j}\,\bar H_f\ \ (1\le j\le N-1),\qquad \bar U_j=\bar R_j+\sum_{f:\ j\in\mathcal S_f}\frac{\partial H_f}{\partial U_j}\,\bar H_f\ \ (j=0,N).

取种子 Rˉ=ψ\bar R=\psi 时这个和是 Uˉj=(ATψ)j=−wj\bar U_j=(A^T\psi)_j=-w_j(第 11 节),所以扇入有已知的总和:在默认解的节点 4 上,四个面加上 −0.0299-0.0299、0.01870.0187、−0.2597-0.2597、0.08340.0834,和为 −0.1875000=−w4-0.1875000=-w_4(图 40)。在边界节点 0 上,约束行先给出 Rˉ0=ψ0=−1.4061\bar R_0=\psi_0=-1.4061,面 0 和面 1 再加上 1.20331.2033 与 0.14030.1403,和是 −0.0625000=−w0=−h/2-0.0625000=-w_0=-h/2:乘子 ψ0\psi_0 的大部分被面的项抵消。如果用覆盖代替累加,只会留下最后一个面的项:下面的点积检验实验可以植入这个错误。

With the seed Rˉ=ψ\bar R=\psi the sum is Uˉj=(ATψ)j=−wj\bar U_j=(A^T\psi)_j=-w_j (Section 11), so the fan-in has a known total: at node 4 of the default solution the four faces add −0.0299-0.0299, 0.01870.0187, −0.2597-0.2597, 0.08340.0834, which sum to −0.1875000=−w4-0.1875000=-w_4 (Figure 40). At the boundary node 0 the constraint row contributes Rˉ0=ψ0=−1.4061\bar R_0=\psi_0=-1.4061 first, faces 0 and 1 add 1.20331.2033 and 0.14030.1403, and the sum is −0.0625000=−w0=−h/2-0.0625000=-w_0=-h/2: most of the multiplier ψ0\psi_0 is cancelled by the face terms. Overwriting instead of adding keeps only the last face's term: the dot-test lab below lets you plant this bug.

图 40 · 节点 4 与节点 0 的扇入(默认设计,种子 R-bar=ψ)。每个读 U_j 的面贡献 (∂ H_f/∂ U_j) H-bar_f,方框里写出它经过的输入(q_L,q_R 是迹,“经斜率”表示通过斜率);边界节点 0 另有约束行的一项 R-bar_0=ψ_0。上:一阶,节点 4(面 3、4);中:无限制器线性,节点 4(面 2–5);下:无限制器线性,节点 0(约束行和面 0、1)。每种情况的和都是 U-bar_j=(A^Tψ)_j=-w_j。一阶,节点 4:2 个面读 U4​f = 3: H̄3​ = −0.1178∂H3​/∂U4​ = −0.6733qR​, UR​+= 0.0793f = 4: H̄4​ = −0.1795∂H4​/∂U4​ = 1.4867qL​, UL​+= −0.2668Ū4​ = Σ = −0.1875000= −w4​ = −0.1875000(因为 AT​ ψ = −w)无限制器线性,节点 4:4 个面读 U4​f = 2: H̄2​ = −0.2963∂H2​/∂U4​ = 0.1008qR​(经斜率)+= −0.0299f = 3: H̄3​ = −0.1466∂H3​/∂U4​ = −0.1276qR​, UR​ + qL​(经斜率)+= 0.0187f = 4: H̄4​ = −0.1793∂H4​/∂U4​ = 1.4486qL​, UL​ + qR​(经斜率)+= −0.2597f = 5: H̄5​ = −0.2337∂H5​/∂U4​ = −0.3568qL​(经斜率)+= 0.0834Ū4​ = Σ = −0.1875000= −w4​ = −0.1875000(因为 AT​ ψ = −w)无限制器线性,节点 0:2 个面读 U0​ + 约束行约束行 0:R̄0​ = ψ0​∂R0​/∂U0​ = 1语句 5′+= −1.4061f = 0: H̄0​ = 1.7095∂H0​/∂U0​ = 0.7039qL​, UL​ + qL​, qR​(经斜率)+= 1.2033f = 1: H̄1​ = −0.3581∂H1​/∂U0​ = −0.3918qL​(经斜率)+= 0.1403Ū0​ = Σ = −0.0625000= −w0​ = −0.0625000(因为 AT​ ψ = −w)
图 40 · 节点 4 与节点 0 的扇入(默认设计,种子 Rˉ=ψ\bar R=\psi)。每个读 UjU_j 的面贡献 (∂Hf/∂Uj) Hˉf(\partial H_f/\partial U_j)\,\bar H_f,方框里写出它经过的输入(qL,qRq_L,q_R 是迹,“经斜率”表示通过斜率);边界节点 0 另有约束行的一项 Rˉ0=ψ0\bar R_0=\psi_0。上:一阶,节点 4(面 3、4);中:无限制器线性,节点 4(面 2–5);下:无限制器线性,节点 0(约束行和面 0、1)。每种情况的和都是 Uˉj=(ATψ)j=−wj\bar U_j=(A^T\psi)_j=-w_j。
Figure 40 · The fan-in at nodes 4 and 0 (default design, seed R-bar=ψ). Every face that reads U_j contributes (∂ H_f/∂ U_j) H-bar_f; its box lists the inputs it goes through (q_L,q_R are traces, "via slopes" means through a slope); the boundary node 0 has one more term, that of its constraint row, R-bar_0=ψ_0. Top: first order, node 4 (faces 3 and 4); middle: unlimited linear, node 4 (faces 2–5); bottom: unlimited linear, node 0 (the constraint row and faces 0 and 1). In every case the sum is U-bar_j=(A^Tψ)_j=-w_j.first order, node 4: 2 faces read U4​f = 3: H̄3​ = −0.1178∂H3​/∂U4​ = −0.6733qR​, UR​+= 0.0793f = 4: H̄4​ = −0.1795∂H4​/∂U4​ = 1.4867qL​, UL​+= −0.2668Ū4​ = Σ = −0.1875000= −w4​ = −0.1875000 (because AT​ ψ = −w)unlimited linear, node 4: 4 faces read U4​f = 2: H̄2​ = −0.2963∂H2​/∂U4​ = 0.1008qR​ (via slopes)+= −0.0299f = 3: H̄3​ = −0.1466∂H3​/∂U4​ = −0.1276qR​, UR​ + qL​ (via slopes)+= 0.0187f = 4: H̄4​ = −0.1793∂H4​/∂U4​ = 1.4486qL​, UL​ + qR​ (via slopes)+= −0.2597f = 5: H̄5​ = −0.2337∂H5​/∂U4​ = −0.3568qL​ (via slopes)+= 0.0834Ū4​ = Σ = −0.1875000= −w4​ = −0.1875000 (because AT​ ψ = −w)unlimited linear, node 0: 2 faces read U0​ + the constraint rowconstraint row 0: R̄0​ = ψ0​∂R0​/∂U0​ = 1statement 5′+= −1.4061f = 0: H̄0​ = 1.7095∂H0​/∂U0​ = 0.7039qL​, UL​ + qL​, qR​ (via slopes)+= 1.2033f = 1: H̄1​ = −0.3581∂H1​/∂U0​ = −0.3918qL​ (via slopes)+= 0.1403Ū0​ = Σ = −0.0625000= −w0​ = −0.0625000 (because AT​ ψ = −w)
Figure 40 · The fan-in at nodes 4 and 0 (default design, seed Rˉ=ψ\bar R=\psi). Every face that reads UjU_j contributes (∂Hf/∂Uj) Hˉf(\partial H_f/\partial U_j)\,\bar H_f; its box lists the inputs it goes through (qL,qRq_L,q_R are traces, "via slopes" means through a slope); the boundary node 0 has one more term, that of its constraint row, Rˉ0=ψ0\bar R_0=\psi_0. Top: first order, node 4 (faces 3 and 4); middle: unlimited linear, node 4 (faces 2–5); bottom: unlimited linear, node 0 (the constraint row and faces 0 and 1). In every case the sum is Uˉj=(ATψ)j=−wj\bar U_j=(A^T\psi)_j=-w_j.

分发的伴随是取值,取值的伴随是分发

The adjoint of a scatter is a gather (and of a gather, a scatter)

这是最该记住的一幅图。前向面循环读入这个面的未知量(取值),把通量写进两行残差(分发)。反向面循环读入两个残差权重(取值,即分发的转置),把这个面的伴随写回它读过的未知量的位置(带 += 的分发,即取值的转置)。循环还是同一个循环,只是两端交换了角色:

This is the picture to remember. The forward face loop reads the unknowns of the face (gather) and writes its flux into two residual rows (scatter). The reverse face loop reads two residual weights (a gather: the transposed scatter) and writes the face's adjoints back into the places of the unknowns it read (a scatter with +=: the transposed gather). It is the same loop; its two ends exchange their roles:

R+=ℬ:,fHf ⟷ Hˉf=ℬ:,fTRˉ,𝐮f=𝒢f𝐔 ⟷ 𝐔ˉ+=𝒢fT𝐮ˉf.R\mathrel{\text{+=}}\mathcal B_{:,f}H_f\ \longleftrightarrow\ \bar H_f=\mathcal B_{:,f}^T\bar R,\qquad \mathbf u_f=\mathcal G_f\mathbf U\ \longleftrightarrow\ \bar{\mathbf U}\mathrel{\text{+=}}\mathcal G_f^T\bar{\mathbf u}_f.

重构的转置也是同样的做法:前向用固定的权重(无限制器线性时 −14,1,14-\tfrac14,1,\tfrac14)把节点值合成迹,反向把迹的伴随用同样的权重分回节点。对内部面(1≤f≤N−21\le f\le N-2):Uˉf−1+=−14qˉL\bar U_{f-1}\mathrel{\text{+=}}-\tfrac14\bar q_L,Uˉf+=qˉL+UˉL+14qˉR\bar U_f\mathrel{\text{+=}}\bar q_L+\bar U_L+\tfrac14\bar q_R,Uˉf+1+=14qˉL+qˉR+UˉR\bar U_{f+1}\mathrel{\text{+=}}\tfrac14\bar q_L+\bar q_R+\bar U_R,Uˉf+2+=−14qˉR\bar U_{f+2}\mathrel{\text{+=}}-\tfrac14\bar q_R:前向矩阵 ZfZ_f 的转置,每个权重原样出现,只是乘在伴随上。面 3 上这四个份额是 0.05750.0575、−0.2256-0.2256、0.01870.0187、−0.0161-0.0161(图 41)。光滑限制器把这些常数换成状态相关的 −σl/2, 1+(σl−σr)/2, σr/2-\sigma_l/2,\ 1+(\sigma_l-\sigma_r)/2,\ \sigma_r/2,边界节点的单侧斜率仍是 Uˉ1+=σˉ0\bar U_1\mathrel{\text{+=}}\bar\sigma_0,Uˉ0+=−σˉ0\bar U_0\mathrel{\text{+=}}-\bar\sigma_0。

The reconstruction is transposed the same way: the forward code combines nodal values into traces with fixed weights (−14,1,14-\tfrac14,1,\tfrac14 for the unlimited linear reconstruction), the reverse code distributes the trace adjoints back to the nodes with the same weights. For an interior face (1≤f≤N−21\le f\le N-2): Uˉf−1+=−14qˉL\bar U_{f-1}\mathrel{\text{+=}}-\tfrac14\bar q_L, Uˉf+=qˉL+UˉL+14qˉR\bar U_f\mathrel{\text{+=}}\bar q_L+\bar U_L+\tfrac14\bar q_R, Uˉf+1+=14qˉL+qˉR+UˉR\bar U_{f+1}\mathrel{\text{+=}}\tfrac14\bar q_L+\bar q_R+\bar U_R, Uˉf+2+=−14qˉR\bar U_{f+2}\mathrel{\text{+=}}-\tfrac14\bar q_R: the transpose of the forward matrix ZfZ_f, every weight appearing unchanged but now multiplying an adjoint. At face 3 the four shares are 0.05750.0575, −0.2256-0.2256, 0.01870.0187 and −0.0161-0.0161 (Figure 41). The smooth limiter replaces these constants by the state-dependent −σl/2, 1+(σl−σr)/2, σr/2-\sigma_l/2,\ 1+(\sigma_l-\sigma_r)/2,\ \sigma_r/2, and the one-sided slope of a boundary node stays Uˉ1+=σˉ0\bar U_1\mathrel{\text{+=}}\bar\sigma_0, Uˉ0+=−σˉ0\bar U_0\mathrel{\text{+=}}-\bar\sigma_0.

图 41 · 分发与取值互为转置(面 3,默认设计,无限制器线性)。上:前向面循环从 U_2,…,U_5 取值,算出 H_3,以 +1、-1 分发到 R_3、R_4。下:反向面循环从 R-bar_3=ψ_3、R-bar_4=ψ_4 取值(H-bar_3=R-bar_3-R-bar_4),把这个面的份额用 += 分发回 U-bar_2,…,U-bar_5。箭头的方向全部反过来,两端互换了角色。前向面循环:取值 → 通量 → 分发UU0​0.9148U1​1.0701U2​1.1708U3​1.1656U4​1.0574U5​0.9129U6​0.8218U7​0.8328U8​0.9148H3​ = H(z3​)= 0.6625取值 G3​:读 4 个未知量RR0​R1​R2​R3​R4​R5​R6​R7​R8​+= 0.6625−= 0.6625分发 B:,3​:写 2 行(+1,−1)反向面循环:分发的转置是取值,取值的转置是带 += 的分发R̄R̄0​ = ψ0​−1.4061R̄1​ = ψ1​−1.7095R̄2​ = ψ2​−1.3514R̄3​ = ψ3​−1.0550R̄4​ = ψ4​−0.9084R̄5​ = ψ5​−0.7291R̄6​ = ψ6​−0.4955R̄7​ = ψ7​−0.2330R̄8​ = ψ8​−0.0870H̄3​ = R̄3​ − R̄4​= −0.1466取值 B:,3​T​:读 2 行(+1,−1)ŪŪ0​Ū1​Ū2​Ū3​Ū4​Ū5​Ū6​Ū7​Ū8​+= 0.0575+= −0.2256+= 0.0187+= −0.0161分发 G3​T​:+= 到 4 个位置
图 41 · 分发与取值互为转置(面 3,默认设计,无限制器线性)。上:前向面循环从 U2,…,U5U_2,\dots,U_5 取值,算出 H3H_3,以 +1+1、−1-1 分发到 R3R_3、R4R_4。下:反向面循环从 Rˉ3=ψ3\bar R_3=\psi_3、Rˉ4=ψ4\bar R_4=\psi_4 取值(Hˉ3=Rˉ3−Rˉ4\bar H_3=\bar R_3-\bar R_4),把这个面的份额用 += 分发回 Uˉ2,…,Uˉ5\bar U_2,\dots,\bar U_5。箭头的方向全部反过来,两端互换了角色。
Figure 41 · Scatter and gather are transposes of each other (face 3, default design, unlimited linear). Top: the forward face loop gathers U_2,…,U_5, computes H_3 and scatters it into R_3 and R_4 with +1 and -1. Bottom: the reverse face loop gathers R-bar_3=ψ_3 and R-bar_4=ψ_4 (H-bar_3=R-bar_3-R-bar_4) and scatters this face's share back into U-bar_2,…,U-bar_5 with +=. Every arrow is reversed; the two ends have exchanged their roles.Forward face loop: gather → flux → scatterUU0​0.9148U1​1.0701U2​1.1708U3​1.1656U4​1.0574U5​0.9129U6​0.8218U7​0.8328U8​0.9148H3​ = H(z3​)= 0.6625gather G3​: reads 4 unknownsRR0​R1​R2​R3​R4​R5​R6​R7​R8​+= 0.6625−= 0.6625scatter B:,3​: writes 2 rows (+1, −1)Reverse face loop: the transpose of the scatter is a gather, the transpose of the gather a scatter with +=R̄R̄0​ = ψ0​−1.4061R̄1​ = ψ1​−1.7095R̄2​ = ψ2​−1.3514R̄3​ = ψ3​−1.0550R̄4​ = ψ4​−0.9084R̄5​ = ψ5​−0.7291R̄6​ = ψ6​−0.4955R̄7​ = ψ7​−0.2330R̄8​ = ψ8​−0.0870H̄3​ = R̄3​ − R̄4​= −0.1466gather B:,3​T​: reads 2 rows (+1, −1)ŪŪ0​Ū1​Ū2​Ū3​Ū4​Ū5​Ū6​Ū7​Ū8​+= 0.0575+= −0.2256+= 0.0187+= −0.0161scatter G3​T​: += into 4 places
Figure 41 · Scatter and gather are transposes of each other (face 3, default design, unlimited linear). Top: the forward face loop gathers U2,…,U5U_2,\dots,U_5, computes H3H_3 and scatters it into R3R_3 and R4R_4 with +1+1 and −1-1. Bottom: the reverse face loop gathers Rˉ3=ψ3\bar R_3=\psi_3 and Rˉ4=ψ4\bar R_4=\psi_4 (Hˉ3=Rˉ3−Rˉ4\bar H_3=\bar R_3-\bar R_4) and scatters this face's share back into Uˉ2,…,Uˉ5\bar U_2,\dots,\bar U_5 with +=. Every arrow is reversed; the two ends have exchanged their roles.

面与面之间不读对方的结果:每个面只读固定的状态和种子,把自己的贡献用 += 加进共用的数组 𝐔ˉ\bar{\mathbf U}、σˉ\bar\sigma、Dˉ\bar D。加法可交换(舍入误差除外),所以反向循环中各个面的先后顺序可以任意(点积实验提供正序 f=0,…,N−1f=0,\dots,N-1 这一选项,检验照样通过)。必须倒过来的是相互依赖的语句的顺序:分发在通量之前,通量在重构之前;斜率语句在原始代码中位于面循环之前,在反向代码中必须位于面循环之后,等读 σj\sigma_j 的面(内部节点两个,端点一个)都把贡献加进 σˉj\bar\sigma_j 之后再倒转。

The faces do not read each other's results: each face reads only the fixed state and the seed and adds its contribution (+=) into the shared arrays 𝐔ˉ\bar{\mathbf U}, σˉ\bar\sigma and Dˉ\bar D. Addition is commutative (up to rounding), so the face order of the reverse loop is free (the dot-test lab offers the forward order f=0,…,N−1f=0,\dots,N-1, and the test still passes); what must be reversed is the order of the statements that depend on each other: the scatter before the flux, the flux before the reconstruction; and the slope statements, which run before the face loop in the primal, run after it in reverse, once the faces that read σj\sigma_j (two for an interior node, one for an end node) have added their parts to σˉj\bar\sigma_j.

反向播放器在当前网格上运行 residual_b。选种子(单位行 eie_i、目标的权重 ww、伴随解 ψ\psi 或随机向量),从约束行开始,经过源项行和面 f=N−1,…,0f=N-1,\dots,0,到斜率;柱条显示 𝐔ˉ\bar{\mathbf U} 和 Dˉ\bar D 的累加,刚更新的分量加框,虚线框是最终值 ATRˉA^T\bar R、RDTRˉR_D^T\bar R。

The reverse player runs residual_b on the current mesh. Choose the seed (a unit row eie_i, the weights ww of the objective, the adjoint solution ψ\psi, or a random vector) and step from the constraint rows through the source rows and the faces f=N−1,…,0f=N-1,\dots,0 to the slopes; the bars show 𝐔ˉ\bar{\mathbf U} and Dˉ\bar D accumulating, the entries just updated framed, the final values ATRˉA^T\bar R and RDTRˉR_D^T\bar R dashed.

用本页的数字反向走同样的面

The same faces in reverse, with the page's numbers

继续看第 8 节的面 3 和面 0,现在以第 11 节伴随方程的解为种子,Rˉ=ψ\bar R=\psi。反向语句先把两个种子汇集成 Hˉf\bar H_f,再乘以同样的五个偏导数;最后两行把它们与第 8 节面表的切向量(种子 (v0,e0)(v_0,e_0))配对:

Continue with the faces 3 and 0 of Section 8, now seeded with the solution of the adjoint equation of Section 11, Rˉ=ψ\bar R=\psi. The reverse statements first gather the two seeds into Hˉf\bar H_f, then multiply by the same five partial derivatives; the last two rows pair them with the tangents of the face table of Section 8 (seed (v0,e0)(v_0,e_0)):

内部面 f=3f=3,种子 Rˉ=ψ\bar R=\psiInterior face f=3f=3, seed Rˉ=ψ\bar R=\psi
量Quantity公式Formula一阶first order无限制器线性unlimited linear光滑限制器smooth limiter
Hˉf\bar H_fψf−ψf+1\psi_f-\psi_{f+1}−0.117835−0.146621−0.134035
qˉL\bar q_LcLHˉfc_L\bar H_f−0.174004−0.229989−0.210349
qˉR\bar q_RcRHˉfc_R\bar H_f0.0699140.0644720.059287
UˉL=−UˉR\bar U_L=-\bar U_RκfHˉf\kappa_f\bar H_f−0.009427−0.011730−0.010723
νˉ\bar\nu−UR−ULdfHˉf-\frac{U_R-U_L}{d_f}\bar H_f−0.131953−0.126877−0.121541
HˉfH˙f\bar H_f\dot H_f输出端output side−0.031291138−0.127115165−0.120330005
zˉfTz˙f\bar z_f^T\dot z_f输入端input side−0.031291138−0.127115165−0.120330005
边界面 f=0f=0,种子 Rˉ=ψ\bar R=\psiBoundary face f=0f=0, seed Rˉ=ψ\bar R=\psi
量Quantity公式Formula一阶first order无限制器线性unlimited linear光滑限制器smooth limiter
Hˉ0\bar H_0−ψ1-\psi_10.8758791.7094781.620440
qˉL\bar q_LcLHˉ0c_L\bar H_01.2765262.5577992.432390
qˉR\bar q_RcRHˉ0c_R\bar H_0−0.428228−0.849485−0.792429
UˉL=−UˉR\bar U_L=-\bar U_Rκ0Hˉ0\kappa_0\bar H_00.0700700.1367580.129635
νˉ\bar\nu−UR−ULd0Hˉ0-\frac{U_R-U_L}{d_0}\bar H_0−0.752072−2.123773−2.263204
Hˉ0H˙0\bar H_0\dot H_0输出端output side−0.643949304−0.228706255−0.166904925
zˉ0Tz˙0\bar z_0^T\dot z_0输入端input side−0.643949304−0.228706255−0.166904925

面 0 只有一行可读:Hˉ0=−Rˉ1=−ψ1\bar H_0=-\bar R_1=-\psi_1(行 0 是约束行,不由面写入),它的两个左侧输入的伴随和其他面一样加进 Uˉ0\bar U_0 与 σˉ0\bar\sigma_0。每个面上输出端与输入端在舍入误差内相等,这就是局部对偶。对整个代码求和时它有了意义:v0v_0 解出切线方程,所以 R˙=0\dot R=0;ψ\psi 解出伴随方程,所以 𝐔ˉ=ATψ=−g\bar{\mathbf U}=A^T\psi=-g。恒等式变成 0=RˉTR˙=−gTv0+Dˉ00=\bar R^T\dot R=-g^Tv_0+\bar D_0,即 Dˉ0=gTv0\bar D_0=g^Tv_0,也就是说,伴随给出的梯度分量等于前向给出的方向导数。无限制器线性时两者都是 −0.178061-0.178061(一阶 −1.175176-1.175176,光滑限制器 −0.188210-0.188210);三种重构、三个分量上 Dˉk\bar D_k 与 gTvkg^Tv_k 相差不超过 1.3×10−151.3\times10^{-15}。

Face 0 has only one row to read: Hˉ0=−Rˉ1=−ψ1\bar H_0=-\bar R_1=-\psi_1 (row 0 is a constraint row, which no face writes), and the adjoints of its two left inputs go into Uˉ0\bar U_0 and σˉ0\bar\sigma_0 like those of every other face. On each face the output and the input side agree to rounding: the local duality. Summed over the whole code it carries meaning: v0v_0 solves the tangent equation, so R˙=0\dot R=0; ψ\psi solves the adjoint equation, so 𝐔ˉ=ATψ=−g\bar{\mathbf U}=A^T\psi=-g. The identity then reads 0=RˉTR˙=−gTv0+Dˉ00=\bar R^T\dot R=-g^Tv_0+\bar D_0, that is Dˉ0=gTv0\bar D_0=g^Tv_0: the gradient component from the adjoint equals the directional derivative from the tangent. For the unlimited linear reconstruction both are −0.178061-0.178061 (first order −1.175176-1.175176, smooth limiter −0.188210-0.188210); over the three reconstructions and the three components Dˉk\bar D_k and gTvkg^Tv_k differ by at most 1.3×10−151.3\times10^{-15}.

点积检验

The dot test

对偶恒等式也是检验反向代码的标准方法:取随机种子 (𝐔˙,D˙)(\dot{\mathbf U},\dot D) 和 Rˉ\bar R,用前向代码算 R˙\dot R,用反向代码算 (𝐔ˉ,Dˉ)(\bar{\mathbf U},\bar D);两边必须在舍入误差内相等,而反向语句中一处错误的转置会让两边相差远大于舍入误差。种子要随机:例如取 D˙=0\dot D=0 时,Dˉ\bar D 里的错误根本看不见。图 42 用一组固定的(非随机)种子把它拆成三个层次:残差层 ∑iRˉiR˙i\sum_i\bar R_i\dot R_i;语句层 ∑fHˉfH˙f+∑fQˉfQ˙f\sum_f\bar H_f\dot H_f+\sum_f\bar Q_f\dot Q_f 再加两个约束行的 Rˉ0R˙0+RˉNR˙N\bar R_0\dot R_0+\bar R_N\dot R_N(因为 R=ℬ(H−Q)R=\mathcal B(H-Q) 加约束行);输入层 ∑jUˉjU˙j+∑kDˉkD˙k\sum_j\bar U_j\dot U_j+\sum_k\bar D_k\dot D_k。逐项不同,总和在舍入误差内相同。

The duality identity is also the standard test of a reverse code: take random seeds (𝐔˙,D˙)(\dot{\mathbf U},\dot D) and Rˉ\bar R, run the forward code for R˙\dot R and the reverse code for (𝐔ˉ,Dˉ)(\bar{\mathbf U},\bar D); the two sides must agree to rounding, and one wrong transpose in the reverse statements makes them differ far beyond rounding. The seeds must be random: with D˙=0\dot D=0, for instance, an error in Dˉ\bar D would be invisible. Figure 42 splits it into three levels with deterministic seeds: the residual level ∑iRˉiR˙i\sum_i\bar R_i\dot R_i; the statement level ∑fHˉfH˙f+∑fQˉfQ˙f\sum_f\bar H_f\dot H_f+\sum_f\bar Q_f\dot Q_f plus the two constraint terms Rˉ0R˙0+RˉNR˙N\bar R_0\dot R_0+\bar R_N\dot R_N (because R=ℬ(H−Q)R=\mathcal B(H-Q) plus the constraint rows); and the input level ∑jUˉjU˙j+∑kDˉkD˙k\sum_j\bar U_j\dot U_j+\sum_k\bar D_k\dot D_k. Term by term the levels differ; the totals agree to rounding.

图 42 · 点积检验的三个层次(默认设计,无限制器线性;种子 U-dot_j=sin(j+0.3),D-dot=(1,1,1),R-bar_i=cos(i+0.4))。上:残差层各项 R-bar_iR-dot_i(i=0,…,N);中:语句层各项 H-bar_fH-dot_f、Q-bar_fQ-dot_f 与约束行的 R-bar_0R-dot_0、R-bar_NR-dot_N;下:输入层各项 U-bar_jU-dot_j 与 D-bar_kD-dot_k。三层的项各不相同,三个总和都是 7.545068809309。同一个内积,三个层次:逐项不同,总和相同残差层R̄i​ Ṙi​012345678Σ =7.545068809309语句层H̄f​ Ḣf​, Q̄f​ Q̇f​, R̄i​ Ṙi​01234567012345670NH̄f​ Ḣf​Q̄f​ Q̇f​约束行Σ =7.545068809309输入层Ūj​ U̇j​, D̄k​ Ḋk​012345678aφνŪj​ U̇j​D̄k​ Ḋk​Σ =7.545068809309
图 42 · 点积检验的三个层次(默认设计,无限制器线性;种子 U˙j=sin⁡(j+0.3)\dot U_j=\sin(j+0.3),D˙=(1,1,1)\dot D=(1,1,1),Rˉi=cos⁡(i+0.4)\bar R_i=\cos(i+0.4))。上:残差层各项 RˉiR˙i\bar R_i\dot R_i(i=0,…,Ni=0,\dots,N);中:语句层各项 HˉfH˙f\bar H_f\dot H_f、QˉfQ˙f\bar Q_f\dot Q_f 与约束行的 Rˉ0R˙0\bar R_0\dot R_0、RˉNR˙N\bar R_N\dot R_N;下:输入层各项 UˉjU˙j\bar U_j\dot U_j 与 DˉkD˙k\bar D_k\dot D_k。三层的项各不相同,三个总和都是 7.5450688093097.545068809309。
Figure 42 · The dot test at three levels (default design, unlimited linear; seeds U-dot_j=sin(j+0.3), D-dot=(1,1,1), R-bar_i=cos(i+0.4)). Top: the residual-level terms R-bar_iR-dot_i (i=0,…,N); middle: the statement-level terms H-bar_fH-dot_f and Q-bar_fQ-dot_f and the constraint terms R-bar_0R-dot_0, R-bar_NR-dot_N; bottom: the input-level terms U-bar_jU-dot_j and D-bar_kD-dot_k. The terms of the three levels differ; the three totals are all 7.545068809309.One inner product at three levels: different terms, the same totalresidualR̄i​ Ṙi​012345678Σ =7.545068809309statementH̄f​ Ḣf​, Q̄f​ Q̇f​, R̄i​ Ṙi​01234567012345670NH̄f​ Ḣf​Q̄f​ Q̇f​rows 0, NΣ =7.545068809309inputŪj​ U̇j​, D̄k​ Ḋk​012345678aφνŪj​ U̇j​D̄k​ Ḋk​Σ =7.545068809309
Figure 42 · The dot test at three levels (default design, unlimited linear; seeds U˙j=sin⁡(j+0.3)\dot U_j=\sin(j+0.3), D˙=(1,1,1)\dot D=(1,1,1), Rˉi=cos⁡(i+0.4)\bar R_i=\cos(i+0.4)). Top: the residual-level terms RˉiR˙i\bar R_i\dot R_i (i=0,…,Ni=0,\dots,N); middle: the statement-level terms HˉfH˙f\bar H_f\dot H_f and QˉfQ˙f\bar Q_f\dot Q_f and the constraint terms Rˉ0R˙0\bar R_0\dot R_0, RˉNR˙N\bar R_N\dot R_N; bottom: the input-level terms UˉjU˙j\bar U_j\dot U_j and DˉkD˙k\bar D_k\dot D_k. The terms of the three levels differ; the three totals are all 7.5450688093097.545068809309.

实验在当前网格、重构和设计上用随机种子重复它,还可以植入手写伴随代码里常见的错误:漏掉或写反的项出现在面循环里(把 += 写成 =、黏性偏导的符号、漏掉 νˉ\bar\nu、漏掉斜率的倒转),也出现在格点格式特有的语句里(漏掉端点的单侧斜率、漏掉约束行、约束行里 uˉin\bar u_{\rm in} 的符号写反、漏掉边界值对 aˉ,φˉ\bar a,\bar\varphi 的贡献),以及漏掉源项行。在默认设计下,对实验的全部网格与种子(N=8N=8 到 128128、三种重构、每种 20 组种子),正确代码两边的相对差至多为 3×10−133\times10^{-13};植入错误后,两边的相对差在 2.6×10−52.6\times10^{-5} 到 2.02.0 之间(最小的是漏掉 νˉ\bar\nu:它只影响一个设计分量)。实验也说明为什么正序运行面循环不是错误,以及一阶时漏掉斜率的倒转(内部节点或端点)为什么不会被发现(σ≡0\sigma\equiv0)。

The lab repeats it with random seeds on the current mesh, reconstruction and design. It also lets you plant one of the bugs a hand-written adjoint typically has: terms lost or reversed inside the face loop (= for +=, the sign of the viscous partials, a forgotten νˉ\bar\nu, the forgotten reversal of the slopes), bugs in the statements that are special to the node scheme (the forgotten one-sided slope of the end nodes, the forgotten constraint rows, the wrong sign of uˉin\bar u_{\rm in} in them, the forgotten contribution of the boundary data to aˉ,φˉ\bar a,\bar\varphi), and the forgotten source rows. At the default design, over the lab's meshes and seeds (N=8N=8 to 128128, the three reconstructions, 20 seed sets each) the two sides of the correct code differ by at most 3×10−133\times10^{-13} (relative), those of the planted bugs by between 2.6×10−52.6\times10^{-5} and 2.02.0 (the smallest is the forgotten νˉ\bar\nu, which affects one design component only). The lab also shows why running the faces in forward order is not a bug, and why forgetting the slope reversal (interior or end nodes) goes unnoticed at first order (σ≡0\sigma\equiv0).

点积检验只能说明反向代码是前向代码的转置,不能说明二者都是残差的导数:如果两者漏掉同一项(比如斜率),检验照样通过。第 8 节中前向导数与差商的对比,以及第 14 节的复数步长,都把前向代码与残差本身对照。

The dot test checks that the reverse code is the transpose of the forward code, not that either is the derivative of the residual: if both forget the same term (say, the slopes) the test still passes. The comparison with finite differences in Section 8 and the complex step of Section 14 check the forward code against the residual itself.

大网格上的同一组恒等式

The same identities on large meshes

上面的实验用浏览器里的稠密求解,网格到 N=128N=128 为止。本格式的独立稀疏 Python 实现(附录 C)在 N=32N=32 到 6553665536 上检验同样的转置关系。每次运行中,反向扫描与伴随求解给出的梯度相差至多 6.2×10−156.2\times10^{-15}(二者用同一个 ψ\psi);另外三个量中前两个取决于线性求解本身的精度,最后一个只涉及存储的矩阵:𝐔ˉ=−w\bar{\mathbf U}=-w,即伴随方程的残差,至多 8.2×10−138.2\times10^{-13};三次前向求解与一次伴随求解的梯度相差至多 4.2×10−124.2\times10^{-12};转置恒等式 𝐧TA𝐦=𝐦TAT𝐧\mathbf n^TA\mathbf m=\mathbf m^TA^T\mathbf n(固定的测试向量 mj=sin⁡7xjm_j=\sin7x_j、nj=cos⁡3xjn_j=\cos3x_j;这是存储的矩阵 AA 本身的恒等式,不是对 residual_b 的检验;误差以 max⁡(1,∣𝐧TA𝐦∣,∣𝐦TAT𝐧∣)\max(1,|\mathbf n^TA\mathbf m|,|\mathbf m^TA^T\mathbf n|) 为分母)至多成立到 3.2×10−123.2\times10^{-12}(图 43)。这三个量随 NN 增大:N=32N=32 时三者中最大的不超过 1.1×10−151.1\times10^{-15},最大的运行(N=65536N=65536)上是 4.2×10−124.2\times10^{-12}。这是数值证据:它说明在这些网格上恒等式至少成立到 5×10−125\times10^{-12},不证明任何东西。

The labs above use the dense solves of the browser and stop at N=128N=128. The independent sparse Python implementation of this scheme (Appendix C) checks the same transposition statements at N=32N=32 to 6553665536. In every run the reverse sweep and the adjoint solve give gradients that differ by at most 6.2×10−156.2\times10^{-15} (both use the same ψ\psi); of the other three quantities the first two depend on the accuracy of the linear solves and the last involves only the stored matrix: 𝐔ˉ=−w\bar{\mathbf U}=-w, the residual of the adjoint equation, holds to at most 8.2×10−138.2\times10^{-13}; the gradients of the three tangent solves and of the one adjoint solve differ by at most 4.2×10−124.2\times10^{-12}; and the transposition identity 𝐧TA𝐦=𝐦TAT𝐧\mathbf n^TA\mathbf m=\mathbf m^TA^T\mathbf n for the fixed test vectors mj=sin⁡7xjm_j=\sin7x_j, nj=cos⁡3xjn_j=\cos3x_j (an identity of the stored matrix AA, not a test of residual_b; the error is divided by max⁡(1,∣𝐧TA𝐦∣,∣𝐦TAT𝐧∣)\max(1,|\mathbf n^TA\mathbf m|,|\mathbf m^TA^T\mathbf n|)) holds to at most 3.2×10−123.2\times10^{-12} (Figure 43). These three quantities grow with NN: at N=32N=32 the largest of them is at most 1.1×10−151.1\times10^{-15}, in the largest run (N=65536N=65536) it is 4.2×10−124.2\times10^{-12}. This is numerical evidence: it shows that the identities hold to at least 5×10−125\times10^{-12} on these meshes and proves nothing.

图 43 · 独立稀疏 Python 实现在大网格上的对偶检验(默认设计,N=32 到 65536,三种重构;紫色圆圈是 N=65536 的无限制器线性运行)。左:三次前向求解与一次伴随求解的梯度之差;右:转置恒等式 n^TAm=m^TA^Tn(固定的测试向量 m_j=sin7x_j、n_j=cos3x_j;存储的矩阵 A 本身的恒等式)的误差,以 max(1,|n^TAm|,|m^TA^Tn|) 为分母。数据来自 Python 运行,不是本页模型的输出(附录 C 给出文件与校验和)。一阶无限制器线性光滑限制器N = 65536(无限制器线性)10-17​10-16​10-15​10-14​10-13​10-12​10-11​10-10​102​103​104​105​区间数 N最大分量之差切向量梯度与伴随梯度之差10-17​10-16​10-15​10-14​10-13​10-12​10-11​10-10​102​103​104​105​区间数 N误差转置恒等式 nT​ A m = mT​ AT​ n(测试向量 sin 7x、cos 3x)
图 43 · 独立稀疏 Python 实现在大网格上的对偶检验(默认设计,N=32N=32 到 6553665536,三种重构;紫色圆圈是 N=65536N=65536 的无限制器线性运行)。左:三次前向求解与一次伴随求解的梯度之差;右:转置恒等式 𝐧TA𝐦=𝐦TAT𝐧\mathbf n^TA\mathbf m=\mathbf m^TA^T\mathbf n(固定的测试向量 mj=sin⁡7xjm_j=\sin7x_j、nj=cos⁡3xjn_j=\cos3x_j;存储的矩阵 AA 本身的恒等式)的误差,以 max⁡(1,∣𝐧TA𝐦∣,∣𝐦TAT𝐧∣)\max(1,|\mathbf n^TA\mathbf m|,|\mathbf m^TA^T\mathbf n|) 为分母。数据来自 Python 运行,不是本页模型的输出(附录 C 给出文件与校验和)。
Figure 43 · The duality checks of the independent sparse Python implementation on large meshes (default design, N=32 to 65536, the three reconstructions; the violet circle is the unlimited linear run at N=65536). Left: the gradients of the three tangent solves minus that of the adjoint solve; right: the error of the transposition identity n^TAm=m^TA^Tn for the fixed test vectors m_j=sin7x_j, n_j=cos3x_j (an identity of the stored matrix A), divided by max(1,|n^TAm|,|m^TA^Tn|). The data come from the Python runs, not from this page's model (Appendix C gives the files and their checksums).first orderunlimited linearsmooth limiterN = 65536 (unlimited linear)10-17​10-16​10-15​10-14​10-13​10-12​10-11​10-10​102​103​104​105​intervals Nlargest component differencetangent gradient minus adjoint gradient10-17​10-16​10-15​10-14​10-13​10-12​10-11​10-10​102​103​104​105​intervals Nerrortransposition identity nT​ A m = mT​ AT​ n(test vectors sin 7x, cos 3x)
Figure 43 · The duality checks of the independent sparse Python implementation on large meshes (default design, N=32N=32 to 6553665536, the three reconstructions; the violet circle is the unlimited linear run at N=65536N=65536). Left: the gradients of the three tangent solves minus that of the adjoint solve; right: the error of the transposition identity 𝐧TA𝐦=𝐦TAT𝐧\mathbf n^TA\mathbf m=\mathbf m^TA^T\mathbf n for the fixed test vectors mj=sin⁡7xjm_j=\sin7x_j, nj=cos⁡3xjn_j=\cos3x_j (an identity of the stored matrix AA), divided by max⁡(1,∣𝐧TA𝐦∣,∣𝐦TAT𝐧∣)\max(1,|\mathbf n^TA\mathbf m|,|\mathbf m^TA^T\mathbf n|). The data come from the Python runs, not from this page's model (Appendix C gives the files and their checksums).

一列与一行:同一个矩阵的两种读法

A column and a row: one matrix read two ways

取种子 𝐔˙=ej\dot{\mathbf U}=e_j,一次前向扫描返回 AA 的第 jj 列(第 8 节);取种子 Rˉ=ei\bar R=e_i,一次反向扫描返回 𝐔ˉ=ATei\bar{\mathbf U}=A^Te_i,即 AA 的第 ii 行,以及 Dˉ=RDTei\bar D=R_D^Te_i,即 RDR_D 的第 ii 行。N+1N+1 次前向扫描或 N+1N+1 次反向扫描得到同一个矩阵,一个按列读,一个按行读。实验逐步做两种扫描并逐元素比较。前向模式适合输入少、输出多的情形,反向模式适合输入多、输出少的情形:一个目标、许多设计变量。

With the seed 𝐔˙=ej\dot{\mathbf U}=e_j one forward sweep returns column jj of AA (Section 8); with the seed Rˉ=ei\bar R=e_i one reverse sweep returns 𝐔ˉ=ATei\bar{\mathbf U}=A^Te_i, row ii of AA, and Dˉ=RDTei\bar D=R_D^Te_i, row ii of RDR_D. N+1N+1 forward sweeps or N+1N+1 reverse sweeps build the same matrix, read by columns or by rows. The lab steps through both and compares them entry by entry. Forward mode suits few inputs and many outputs, reverse mode many inputs and few outputs: one objective and many design variables.

解出来的伴随,以及它省下的代价

The solved adjoint, and what it saves

目标沿设计方向的导数是 J˙h=gTv\dot J_h=g^Tv,其中 Av=−RDD˙Av=-R_D\dot D(第 8 节)。写成 v=−A−1RDD˙v=-A^{-1}R_D\dot D,再把逆矩阵移到内积的另一边:J˙h=−gTA−1RDD˙=ψTRDD˙\dot J_h=-g^TA^{-1}R_D\dot D=\psi^TR_D\dot D,其中 ψ=−A−Tg\psi=-A^{-T}g,也就是

The derivative of the objective along a design direction is J˙h=gTv\dot J_h=g^Tv with Av=−RDD˙Av=-R_D\dot D (Section 8). Write v=−A−1RDD˙v=-A^{-1}R_D\dot D and move the inverse to the other side of the dot product: J˙h=−gTA−1RDD˙=ψTRDD˙\dot J_h=-g^TA^{-1}R_D\dot D=\psi^TR_D\dot D with ψ=−A−Tg\psi=-A^{-T}g, that is

ATψ=−g,g=(∂Jh∂𝐔)T=w,dJh/dD=ψTRD.A^T\psi=-g,\qquad g=\Big(\frac{\partial J_h}{\partial\mathbf U}\Big)^T=w,\qquad \mathrm dJ_h/\mathrm dD=\psi^TR_D.

(JhJ_h 不直接依赖设计,所以梯度里没有 ∂Jh/∂D\partial J_h/\partial D 一项。)反向代码提供这个乘积:以 Rˉ=ψ\bar R=\psi 为种子,它返回 𝐔ˉ=ATψ\bar{\mathbf U}=A^T\psi(在解处等于 −g-g,可作检验:三种重构的最大偏差是 5.3×10−165.3\times10^{-16})和 Dˉ=RDTψ\bar D=R_D^T\psi,即梯度行的转置:一次扫描得到全部三个分量,其中包括约束行里 −ψ0 ∂uin/∂D−ψN ∂uout/∂D-\psi_0\,\partial u_{\rm in}/\partial D-\psi_N\,\partial u_{\rm out}/\partial D 那两项。前向代码每个设计分量需要一次扫描(以及一次求解 Avk=−RDekAv_k=-R_De_k,第 10 节);反向代码不论有多少设计变量,只需一次伴随求解和一次扫描。这里有 3 个分量,所以是 3 比 1;对于有几百个设计变量的外形设计,就是几百比 1。第 11 节解伴随方程,第 12 节按设计进入残差的位置拆分梯度。图 44 把两条路线并排画出;下面的实验在你的浏览器里测量一次扫描相当于几次残差计算。

(JhJ_h has no direct design dependence, so the gradient has no ∂Jh/∂D\partial J_h/\partial D term.) The reverse code supplies the product: seeded with Rˉ=ψ\bar R=\psi it returns 𝐔ˉ=ATψ\bar{\mathbf U}=A^T\psi (equal to −g-g at the solution, a check: the largest deviation over the three reconstructions is 5.3×10−165.3\times10^{-16}) and Dˉ=RDTψ\bar D=R_D^T\psi, the transpose of the gradient row: all three components from one sweep, the two terms −ψ0 ∂uin/∂D−ψN ∂uout/∂D-\psi_0\,\partial u_{\rm in}/\partial D-\psi_N\,\partial u_{\rm out}/\partial D of the constraint rows included. The forward code needs one sweep per design component (and one solve Avk=−RDekAv_k=-R_De_k each, Section 10); the reverse code needs one adjoint solve and one sweep, whatever the number of design variables. Here there are 3 components, so the saving is 3 to 1; for a shape with hundreds of design variables it is hundreds to one. Section 11 solves the adjoint equation, and Section 12 splits the gradient by the places where the design enters the residual. Figure 44 draws the two routes side by side; the lab below measures, in your browser, how many residual evaluations one sweep costs.

图 44 · 到梯度 dJ_h/ dD 的两条路线(默认设计,无限制器线性)。左:前向路线,3 个设计种子各做一次前向扫描和一次线性求解,再取点积 g^Tv_k。右:伴随路线,一次转置求解 A^Tψ=-g 和一次种子为 ψ 的反向扫描,直接给出三个分量。下方的数字是两条路线各自的结果,它们的差不超过 1.3 × 10^(-15);它们是离散目标 J_h 的导数,不是连续目标 J 的梯度(第 12 节与第 16 节比较两者)。到梯度 dJh​/dD 的两条路前向路线:每个设计变量一次求解种子 Ḋ = ek​,k = a, φ, ν3 次前向扫描得到 RD​ ek​(第 8 节)A vk​ = −RD​ ek​3 次线性求解(第 10 节)J̇k​ = gT​ vk​3 个点积伴随路线:一次求解给出全部设计变量目标的权重 g = w(不含设计)已知,不需要扫描AT​ ψ = −g1 次线性求解(第 11 节)反向扫描,R̄ = ψ:D̄ = RD​T​ ψ1 次反向扫描(本节)dJh​/da−0.1780612dJh​/dφ0.4199039dJh​/dν0.0039088默认设计,无限制器线性dJh​/da−0.1780612dJh​/dφ0.4199039dJh​/dν0.0039088默认设计,无限制器线性两条路线的差不超过 1.3×10−15​;p 个设计变量要 p 次前向求解,伴随只要 1 次:这里 p = 3。
图 44 · 到梯度 dJh/dD\mathrm dJ_h/\mathrm dD 的两条路线(默认设计,无限制器线性)。左:前向路线,3 个设计种子各做一次前向扫描和一次线性求解,再取点积 gTvkg^Tv_k。右:伴随路线,一次转置求解 ATψ=−gA^T\psi=-g 和一次种子为 ψ\psi 的反向扫描,直接给出三个分量。下方的数字是两条路线各自的结果,它们的差不超过 1.3×10−151.3\times10^{-15};它们是离散目标 JhJ_h 的导数,不是连续目标 JJ 的梯度(第 12 节与第 16 节比较两者)。
Figure 44 · Two routes to the gradient dJ_h/ dD (default design, unlimited linear). Left: the tangent route, one forward sweep and one linear solve for each of the 3 design seeds, then the dot product g^Tv_k. Right: the adjoint route, one transposed solve A^Tψ=-g and one reverse sweep with the seed ψ, which gives all three components at once. The numbers below are the results of the two routes; they differ by at most 1.3 × 10^(-15). They are the derivative of the discrete objective J_h, not the gradient of the continuous J (Sections 12 and 16 compare the two).Two routes to the gradient dJh​/dDTangent route: one solve per design variableseeds Ḋ = ek​, k = a, φ, ν3 tangent sweeps give RD​ ek​ (Section 8)A vk​ = −RD​ ek​3 linear solves (Section 10)J̇k​ = gT​ vk​3 dot productsAdjoint route: one solve for all design variablesobjective weights g = w (no design)known, no sweep neededAT​ ψ = −g1 linear solve (Section 11)reverse sweep, R̄ = ψ: D̄ = RD​T​ ψ1 reverse sweep (this section)dJh​/da−0.1780612dJh​/dφ0.4199039dJh​/dν0.0039088default design, unlimited lineardJh​/da−0.1780612dJh​/dφ0.4199039dJh​/dν0.0039088default design, unlimited linearThe two routes differ by at most 1.3×10−15​; p design variables need p tangent solves, the adjoint route one: here p = 3.
Figure 44 · Two routes to the gradient dJh/dD\mathrm dJ_h/\mathrm dD (default design, unlimited linear). Left: the tangent route, one forward sweep and one linear solve for each of the 3 design seeds, then the dot product gTvkg^Tv_k. Right: the adjoint route, one transposed solve ATψ=−gA^T\psi=-g and one reverse sweep with the seed ψ\psi, which gives all three components at once. The numbers below are the results of the two routes; they differ by at most 1.3×10−151.3\times10^{-15}. They are the derivative of the discrete objective JhJ_h, not the gradient of the continuous JJ (Sections 12 and 16 compare the two).

从前向到伴随:转置让语句倒着执行

From tangent to adjoint: the transpose runs the statements backwards

先说明反向累加为什么给出矩阵的转置:展平之后,下面只是交换两个有限和(Dˉ\bar D 同理):

First, why reverse accumulation gives the matrix transpose: after flattening, the following merely exchanges two finite sums (Dˉ\bar D alike):

RˉTR˙=∑i∑jRˉi ∂Ri∂Uj U˙j=∑jU˙j(∑i∂Ri∂UjRˉi)=𝐔˙T(ATRˉ).\bar R^T\dot R=\sum_i\sum_j\bar R_i\,\frac{\partial R_i}{\partial U_j}\,\dot U_j=\sum_j\dot U_j\Big(\sum_i\frac{\partial R_i}{\partial U_j}\bar R_i\Big)=\dot{\mathbf U}^T\big(A^T\bar R\big).

一个面的前向导数是四个初等 Jacobian 的乘积(第 8 节)。乘积的转置是各转置按相反顺序相乘:

The tangent of one face is the product of four elementary Jacobians (Section 8). The transpose of a product is the product of the transposes in the reverse order:

AfT=(ℬ:,fHz,fZf𝒢f)T=𝒢fTZfTHz,fTℬ:,fT,(ℬ:,fHz,fKf)T=KfTHz,fTℬ:,fT.A_f^T=\big(\mathcal B_{:,f}H_{z,f}Z_f\mathcal G_f\big)^T=\mathcal G_f^TZ_f^TH_{z,f}^T\mathcal B_{:,f}^T,\qquad \big(\mathcal B_{:,f}H_{z,f}K_f\big)^T=K_f^TH_{z,f}^T\mathcal B_{:,f}^T.

从右往左读,就是反向扫描的顺序:程序最后执行的分发最先倒转,最先执行的取值最后倒转。把所有伴随置零,以 Rˉ\bar R 为种子,对每个面执行:

Read from right to left, this is the order of the reverse sweep: the scatter, which the program ran last, comes first, and the gather, which it ran first, comes last. Zero every adjoint, seed with Rˉ\bar R, and run for every face:

(0) 𝐔ˉ←0, Dˉ←0;(4′) Hˉf=ℬ:,fTRˉ=Rˉf−Rˉf+1;(3′) zˉf=Hz,fTHˉf;(2′) 𝐮ˉf=ZfTzˉf,  Dˉ+=KfTzˉf;(1′) 𝐔ˉ+=𝒢fT𝐮ˉf,(0)\ \bar{\mathbf U}\leftarrow0,\ \bar D\leftarrow0;\qquad (4')\ \bar H_f=\mathcal B_{:,f}^T\bar R=\bar R_f-\bar R_{f+1};\qquad (3')\ \bar z_f=H_{z,f}^T\bar H_f;\qquad (2')\ \bar{\mathbf u}_f=Z_f^T\bar z_f,\ \ \bar D\mathrel{\text{+=}}K_f^T\bar z_f;\qquad (1')\ \bar{\mathbf U}\mathrel{\text{+=}}\mathcal G_f^T\bar{\mathbf u}_f,

源项行 R-=SR\mathrel{\text{-=}}S 也按同样的规则倒转:Sˉ=−Rˉ\bar S=-\bar R,Dˉ+=(∂S/∂D)TSˉ\bar D\mathrel{\text{+=}}(\partial S/\partial D)^T\bar S(没有状态项:∂S/∂𝐔=0\partial S/\partial\mathbf U=0);两个约束行按 Uˉ0+=Rˉ0\bar U_0\mathrel{\text{+=}}\bar R_0、uˉin-=Rˉ0\bar u_{\rm in}\mathrel{\text{-=}}\bar R_0 倒转。对偶恒等式逐级成立:每一步用一次转置的定义,把一个初等 Jacobian 移到内积的另一边,所以每一级的内积都相同:

The source rows R-=SR\mathrel{\text{-=}}S are reversed by the same rule: Sˉ=−Rˉ\bar S=-\bar R, Dˉ+=(∂S/∂D)TSˉ\bar D\mathrel{\text{+=}}(\partial S/\partial D)^T\bar S (no state term: ∂S/∂𝐔=0\partial S/\partial\mathbf U=0); the two constraint rows are reversed by Uˉ0+=Rˉ0\bar U_0\mathrel{\text{+=}}\bar R_0, uˉin-=Rˉ0\bar u_{\rm in}\mathrel{\text{-=}}\bar R_0. The duality identity holds stage by stage: each step uses the definition of the transpose once to move one elementary Jacobian across the dot product, so the inner product is the same at every stage:

RˉT(ℬ:,fH˙f)=HˉfH˙f=HˉfHz,fz˙f=zˉfTz˙f=𝐮ˉfT𝐮˙f+(KfTzˉf)TD˙=(𝒢fT𝐮ˉf)T𝐔˙+(KfTzˉf)TD˙.\bar R^T\big(\mathcal B_{:,f}\dot H_f\big)=\bar H_f\dot H_f=\bar H_fH_{z,f}\dot z_f=\bar z_f^T\dot z_f=\bar{\mathbf u}_f^T\dot{\mathbf u}_f+\big(K_f^T\bar z_f\big)^T\dot D=\big(\mathcal G_f^T\bar{\mathbf u}_f\big)^T\dot{\mathbf U}+\big(K_f^T\bar z_f\big)^T\dot D.

对所有面求和,再加上源项一对 SˉTS˙\bar S^T\dot S 和约束行的两对 Rˉ0R˙0+RˉNR˙N\bar R_0\dot R_0+\bar R_N\dot R_N,右边正好累加成反向扫描的输出:RˉTR˙=𝐔ˉT𝐔˙+DˉTD˙\bar R^T\dot R=\bar{\mathbf U}^T\dot{\mathbf U}+\bar D^T\dot D。

Summed over the faces, with the source pair SˉTS˙\bar S^T\dot S and the two constraint pairs Rˉ0R˙0+RˉNR˙N\bar R_0\dot R_0+\bar R_N\dot R_N added, the right side accumulates exactly into the outputs of the reverse sweep: RˉTR˙=𝐔ˉT𝐔˙+DˉTD˙\bar R^T\dot R=\bar{\mathbf U}^T\dot{\mathbf U}+\bar D^T\dot D.

算例:面 3 的反向扫描,种子 Rˉ=ψ\bar R=\psi,与第 8 节末尾的前向算例(种子 (v1,e1)(v_1,e_1),相位)配对。最后一列是每一级的内积;第一级 RˉT(ℬ:,3H˙3)\bar R^T(\mathcal B_{:,3}\dot H_3) 只用面 3 对第 3、4 行的贡献 ±H˙3\pm\dot H_3,而不是完整的 R˙3,R˙4\dot R_3,\dot R_4(后者在这个种子下为零):

A worked example: the reverse sweep of face 3 with the seed Rˉ=ψ\bar R=\psi, paired with the forward example at the end of Section 8 (seed (v1,e1)(v_1,e_1), the phase). The last column is the inner product at each stage; the first stage, RˉT(ℬ:,3H˙3)\bar R^T(\mathcal B_{:,3}\dot H_3), uses face 3's contributions ±H˙3\pm\dot H_3 to rows 3 and 4 only, not the full R˙3,R˙4\dot R_3,\dot R_4 (which vanish for this seed):

语句Statement量Quantity伴随值Adjoint内积Inner product
(0)置零(0) zero𝐔ˉ←0, Dˉ←0\bar{\mathbf U}\leftarrow0,\ \bar D\leftarrow00
(4′)种子(4′) seedRˉ3=ψ3, Rˉ4=ψ4\bar R_3=\psi_3,\ \bar R_4=\psi_4−1.05504, −0.90842RˉT(ℬ:,3H˙3)=\bar R^T(\mathcal B_{:,3}\dot H_3)= −0.1716056056
(4′)取值(4′) gatherHˉ3=Rˉ3−Rˉ4\bar H_3=\bar R_3-\bar R_4−0.146621Hˉ3H˙3=\bar H_3\dot H_3= −0.1716056056
(3′)通量的转置(3′) flux, transposedqˉL, qˉR\bar q_L,\ \bar q_R−0.229989, 0.064472zˉ3Tz˙3=\bar z_3^T\dot z_3= −0.1716056056
UˉL, UˉR, νˉ\bar U_L,\ \bar U_R,\ \bar\nu−0.011730, 0.011730, −0.126877
(2′)(1′)加回(2′)(1′) add backUˉ2, Uˉ3+=\bar U_2,\ \bar U_3\mathrel{\text{+=}}0.057497, −0.225601𝐮ˉ3T𝐮˙3+DˉTD˙=\bar{\mathbf u}_3^T\dot{\mathbf u}_3+\bar D^T\dot D= −0.1716056056
Uˉ4, Uˉ5+=\bar U_4,\ \bar U_5\mathrel{\text{+=}}0.018705, −0.016118
φˉ+=\bar\varphi\mathrel{\text{+=}}0

四个内积在舍入误差内相等(最大相对差 6.5×10−166.5\times10^{-16}),对偶在这个面上逐级成立。面 3 不直接依赖 φ\varphi(任何面都不直接依赖),所以它对 Dˉ1\bar D_1 的贡献是 0;φ\varphi 只经过约束行和源项行进入 Dˉ\bar D。这个面的 νˉ\bar\nu 虽然不为零,但种子 D˙=e1\dot D=e_1 的 ν˙=0\dot\nu=0,所以 νˉ\bar\nu 不进入这里的内积。下面的播放器对任意面重放这四步,并在每一步显示内积。

The four inner products agree to rounding (largest relative difference 6.5×10−166.5\times10^{-16}): the duality holds stage by stage on this face. Face 3 does not depend on φ\varphi directly (no face does), so its contribution to Dˉ1\bar D_1 is 0; the phase reaches Dˉ\bar D only through the constraint rows and the source rows. The νˉ\bar\nu of this face is not zero, but the seed D˙=e1\dot D=e_1 has ν˙=0\dot\nu=0, so it does not enter these inner products. The player below replays the four steps for any face and shows the inner product at each.

第 10 节Section 10

前向求解:解随设计怎样变化

The tangent solve: how the solution moves with the design

本节实验:振幅 aa 增加 0.010.01 时,N=8N=8 网格上的每个 UjU_j 变化多少?JhJ_h 又变化多少?先猜哪几个节点变化最大,再读图 45,并用本节的前向求解面板核对。

Experiment: If the amplitude aa grows by 0.010.01, how much does each UjU_j of the N=8N=8 mesh move, and how much does JhJ_h move? Guess which nodes move most, then read Figure 45 and check the guess in this section's tangent-solve panel.

第 8 节逐条语句地对残差代码求导:给定种子 𝐔˙\dot{\mathbf U} 与 D˙\dot D,前向代码返回 R˙=A𝐔˙+RDD˙\dot R=A\dot{\mathbf U}+R_D\dot D。它算的是一个乘积,还没有回答“设计变了,解怎样变”。本节用同一段代码来回答这个问题:设计沿 D˙\dot D 移动时,什么样的 𝐔˙\dot{\mathbf U} 能让残差一直保持为零?

Section 8 differentiated the residual code statement by statement: for seeds 𝐔˙\dot{\mathbf U} and D˙\dot D the tangent code returns R˙=A𝐔˙+RDD˙\dot R=A\dot{\mathbf U}+R_D\dot D. That is a product; it does not yet say how the solution moves when the design moves. This section puts that question to the same code: when the design moves along D˙\dot D, which 𝐔˙\dot{\mathbf U} keeps the residual at zero?

从前向代码到一个线性方程组

From the tangent code to one linear system

收敛解随设计变化:在默认设计附近,每个设计 DD 都有自己的离散解 𝐔(D)\mathbf U(D),满足 R(𝐔(D),D)=0R(\mathbf U(D),D)=0(Newton 迭代求出它,第 5 节)。让设计沿直线 D+t ekD+t\,e_k 移动,eke_k 是第 kk 个分量的单位向量(k=0,1,2k=0,1,2 依次对应 a,φ,νa,\varphi,\nu),tt 是实数。残差对每个 tt 都是零,所以它对 tt 的导数也是零。在 t=0t=0 用链式法则求导——这正是对整个求解过程使用前向模式——得到两项:

The converged state depends on the design: near the default, every design DD has its own discrete solution 𝐔(D)\mathbf U(D) with R(𝐔(D),D)=0R(\mathbf U(D),D)=0 (Newton's method finds it, Section 5). Move the design along the straight line D+t ekD+t\,e_k, where eke_k is the unit vector of component kk (k=0,1,2k=0,1,2 for a,φ,νa,\varphi,\nu) and tt is a real number. The residual is zero for every tt, so its derivative with respect to tt is zero as well. The chain rule at t=0t=0, which is the forward mode applied to the whole solve, gives two terms:

0=ddtR(𝐔(D+t ek), D+t ek)∣t=0=A vk+RD ek,vk=∂𝐔∂Dk.0=\frac{\mathrm d}{\mathrm dt}R\bigl(\mathbf U(D+t\,e_k),\,D+t\,e_k\bigr)\Big|_{t=0}=A\,v_k+R_D\,e_k,\qquad v_k=\frac{\partial\mathbf U}{\partial D_k}.

第一项是设计经由状态产生的间接影响,第二项是设计直接改变残差的部分。于是状态切向量 vkv_k 是一个线性方程组的解:矩阵是收敛状态处的状态 Jacobian A=R𝐔A=R_{\mathbf U}((N+1)×(N+1)(N+1)\times(N+1),第一行与最后一行是两个约束的单位行,第 4 节),右端是残差自身对设计的导数:

The first term is the indirect effect of the design through the state, the second is the direct change of the residual. So the state tangent vkv_k solves a linear system whose matrix is the state Jacobian A=R𝐔A=R_{\mathbf U} at the converged state ((N+1)×(N+1)(N+1)\times(N+1); its first and last row are the identity rows of the two constraints, Section 4) and whose right-hand side is the residual's own design derivative:

A vk=−RD ek,k=0,1,2.A\,v_k=-R_D\,e_k,\qquad k=0,1,2.

用第 8 节的话说:vk≡𝐔˙v_k\equiv\dot{\mathbf U},种子是 D˙=ek\dot D=e_k;把 (𝐔˙,D˙)=(vk,ek)(\dot{\mathbf U},\dot D)=(v_k,e_k) 送进前向代码,返回的 R˙\dot R 是零。前向代码对给定的 𝐔˙\dot{\mathbf U} 计算 R˙\dot R,前向求解则是找出使 R˙=0\dot R=0 的那个 𝐔˙\dot{\mathbf U}。本页对 AA 做 LU 分解来解这个方程组(第 17 节改用 GS 与 GMRES)。这要求 AA 在收敛状态处非奇异:本页每个状态上分解都成功——这是数值检查,不是定理。默认设计下三次求解的线性残差 max⁡k∥Avk+RDek∥∞\max_k\|Av_k+R_De_k\|_\infty 低于 10−1510^{-15}(舍入误差)。

In the words of Section 8: vk≡𝐔˙v_k\equiv\dot{\mathbf U} for the seed D˙=ek\dot D=e_k; fed with the seeds (𝐔˙,D˙)=(vk,ek)(\dot{\mathbf U},\dot D)=(v_k,e_k), the tangent code returns R˙=0\dot R=0. The tangent code evaluates R˙\dot R for a given 𝐔˙\dot{\mathbf U}; the tangent solve finds the 𝐔˙\dot{\mathbf U} that makes R˙\dot R vanish. The page solves the system with an LU factorisation of AA (Section 17 uses GS and GMRES instead). This needs AA to be nonsingular at the converged state: the factorisation succeeds at every state of this page, a numerical check rather than a theorem. At the default design the linear residual of the three solves, max⁡k∥Avk+RDek∥∞\max_k\|Av_k+R_De_k\|_\infty, is below 10−1510^{-15} (round-off).

vkv_k 是什么

What vkv_k is

vkv_k 有 N+1N+1 个分量:它是每个节点值对设计分量 DkD_k 的响应,是整个离散解的灵敏度,不只是一个数。其中两个分量不用求解就知道:约束行说 U0=uin(D)U_0=u_{\rm in}(D)、UN=uout(D)U_N=u_{\rm out}(D),所以 vk,0=∂uin/∂Dkv_{k,0}=\partial u_{\rm in}/\partial D_k、vk,N=∂uout/∂Dkv_{k,N}=\partial u_{\rm out}/\partial D_k 精确成立(这里与它们相差不到 10−1510^{-15})。目标的导数由 vkv_k 得到一个数:第 7 节的 Jh=wT𝐔J_h=w^T\mathbf U 不显含设计(权重 wj=Wj(1+xj)w_j=W_j(1+x_j) 只依赖网格),所以 JD=0J_D=0,导数就是加权和

vkv_k has N+1N+1 entries: it is the response of every nodal value to the design component DkD_k, the sensitivity of the whole discrete solution and not of one number. Two of its entries are known without solving anything: the constraint rows say U0=uin(D)U_0=u_{\rm in}(D) and UN=uout(D)U_N=u_{\rm out}(D), so vk,0=∂uin/∂Dkv_{k,0}=\partial u_{\rm in}/\partial D_k and vk,N=∂uout/∂Dkv_{k,N}=\partial u_{\rm out}/\partial D_k exactly (here they agree to within 10−1510^{-15}). One number follows from vkv_k. The objective Jh=wT𝐔J_h=w^T\mathbf U of Section 7 does not contain the design explicitly (the weights wj=Wj(1+xj)w_j=W_j(1+x_j) depend on the mesh only), so JD=0J_D=0 and its derivative is the weighted sum

J˙k=gTvk=wTvk=dJhdDk.\dot J_k=g^Tv_k=w^Tv_k=\frac{\mathrm dJ_h}{\mathrm dD_k}.

默认设计(N=8N=8,无限制器线性重构)下三次求解给出 J˙0=−0.178061\dot J_0=−0.178061、J˙1=0.419904\dot J_1=0.419904、J˙2=0.003909\dot J_2=0.003909。它们是这个网格上离散目标 Jh(D)J_h(D) 的精确导数,与第 1 节的连续梯度 (−0.144008, 0.085156, 0.000000)(−0.144008,\ 0.085156,\ 0.000000) 比:dJh/da\mathrm dJ_h/\mathrm da 相差 23.6%,dJh/dφ\mathrm dJ_h/\mathrm d\varphi 相差 393%,dJh/dν\mathrm dJ_h/\mathrm d\nu 是 0.00390.0039 而不是零。格心页同一网格上,aa 与 ν\nu 的梯度误差分别是这里的 10 倍与 79 倍,φ\varphi 的梯度误差却比这里小(0.146 对 0.335;第 12 节的比较表)。这里 aa 的梯度比较好,有两个原因,第 12 节都量过:默认相位恰好靠近 aa 的梯度误差随相位变化的一个零点;两个边界节点用单侧斜率做了二阶重构(不重构它们时 N=8N=8 的误差是 −0.671−0.671)。φ\varphi 的误差主要来自源项部分(第 12 节)。此外,一个正弦周期只有 8 个节点,而精确梯度只是两个 O(1)O(1) 项之间很小的差。实验的答案在图 45 左图:aa 增加 0.010.01 时,变化最大的是 U6U_{6} 与 U2U_{2},约 −0.0089−0.0089 与 0.00860.0086;JhJ_h 变化约 0.01 J˙0=−0.001780.01\,\dot J_0=−0.00178。

At the default design (N=8N=8, unlimited linear reconstruction) the three solves give J˙0=−0.178061\dot J_0=−0.178061, J˙1=0.419904\dot J_1=0.419904 and J˙2=0.003909\dot J_2=0.003909. These are the exact derivatives of the discrete objective Jh(D)J_h(D) on this mesh. Against the continuous gradient (−0.144008, 0.085156, 0.000000)(−0.144008,\ 0.085156,\ 0.000000) of Section 1: dJh/da\mathrm dJ_h/\mathrm da is 23.6% off, dJh/dφ\mathrm dJ_h/\mathrm d\varphi is 393% off, and dJh/dν\mathrm dJ_h/\mathrm d\nu is 0.00390.0039 instead of zero. On the same mesh the cell-centred page's gradient errors for aa and ν\nu are 10 and 79 times as large as these, but its error for φ\varphi is the smaller one (0.146 against 0.335; the comparison table of Section 12). The amplitude gradient is comparatively good here for two reasons that Section 12 measures: the default phase happens to lie near a zero of the error of the aa-gradient as a function of the phase, and the two boundary nodes are reconstructed at second order with a one-sided slope (with the boundary nodes not reconstructed the error at N=8N=8 is −0.671−0.671). The error of φ\varphi comes mainly from the source part (Section 12). In addition, 8 nodes per period of the sine are few, and the exact gradient is a small difference of two terms of order one. The left panel of Figure 45 answers the experiment: when aa grows by 0.010.01, the nodes that move most are U6U_{6} and U2U_{2}, by about −0.0089−0.0089 and 0.00860.0086, and JhJ_h moves by about 0.01 J˙0=−0.001780.01\,\dot J_0=−0.00178.

图 45 · 默认设计下的三个切线解(N=8):三种重构的 v_k=∂U/∂ D_k(点、圈、方块)与连续切线 ∂ u*/∂ D_k(曲线,本节末尾推导)。两端的值精确落在曲线上;内部节点只粗略地跟随连续切线;黏性切向量 v_2 明显不为零,尽管 u* 与 ν 无关。每幅图左上角是无限制器线性重构的 J-dot_k=w^Tv_k。连续切线 ∂u*/∂Dk​无限制器线性一阶光滑限制器−1.5−1−0.500.5100.51xvk​k = 0:振幅 aJ̇0​ = −0.1781−1−0.500.511.500.51xk = 1:相位 φJ̇1​ = 0.4199−0.500.511.500.51xk = 2:黏性 νJ̇2​ = 0.0039
图 45 · 默认设计下的三个切线解(N=8N=8):三种重构的 vk=∂𝐔/∂Dkv_k=\partial\mathbf U/\partial D_k(点、圈、方块)与连续切线 ∂u∗/∂Dk\partial u^*/\partial D_k(曲线,本节末尾推导)。两端的值精确落在曲线上;内部节点只粗略地跟随连续切线;黏性切向量 v2v_2 明显不为零,尽管 u∗u^* 与 ν\nu 无关。每幅图左上角是无限制器线性重构的 J˙k=wTvk\dot J_k=w^Tv_k。
Figure 45 · The three tangent solutions at the default design (N=8): v_k=∂U/∂ D_k of the three reconstructions (dots, rings, squares) and the continuous tangent ∂ u*/∂ D_k (curve, derived at the end of this section). The two end values lie exactly on the curve; the interior nodes follow it only roughly; the viscosity tangent v_2 is clearly not zero although u* does not depend on ν. Each panel shows J-dot_k=w^Tv_k of the unlimited linear reconstruction at its top left.continuous tangent ∂u*/∂Dk​unlimited linearfirst ordersmooth limiter−1.5−1−0.500.5100.51xvk​k = 0: amplitude aJ̇0​ = −0.1781−1−0.500.511.500.51xk = 1: phase φJ̇1​ = 0.4199−0.500.511.500.51xk = 2: viscosity νJ̇2​ = 0.0039
Figure 45 · The three tangent solutions at the default design (N=8N=8): vk=∂𝐔/∂Dkv_k=\partial\mathbf U/\partial D_k of the three reconstructions (dots, rings, squares) and the continuous tangent ∂u∗/∂Dk\partial u^*/\partial D_k (curve, derived at the end of this section). The two end values lie exactly on the curve; the interior nodes follow it only roughly; the viscosity tangent v2v_2 is clearly not zero although u∗u^* does not depend on ν\nu. Each panel shows J˙k=wTvk\dot J_k=w^Tv_k of the unlimited linear reconstruction at its top left.

为什么 v2≠0v_2\neq0?精确解 u∗u^* 与 ν\nu 无关,离散解却有关:格式的误差依赖 ν\nu(默认网格的网格 Péclet 数是 uinh/ν≈11.4u_{\rm in}h/\nu\approx11.4),ν\nu 一变,误差就变,𝐔\mathbf U 也跟着变。所以 J˙2=dJh/dν\dot J_2=\mathrm dJ_h/\mathrm d\nu 在粗网格上不为零,而连续的 dJ/dν=0\mathrm dJ/\mathrm d\nu=0;第 12 节把这个差别拆开来看。

Why is v2≠0v_2\neq0? The exact solution u∗u^* does not depend on ν\nu, but the discrete solution does: the error of the scheme depends on ν\nu (the mesh Péclet number of the default mesh is uinh/ν≈11.4u_{\rm in}h/\nu\approx11.4), so when ν\nu changes the error changes and 𝐔\mathbf U with it. That is why J˙2=dJh/dν\dot J_2=\mathrm dJ_h/\mathrm d\nu is not zero on a coarse mesh while the continuous dJ/dν=0\mathrm dJ/\mathrm d\nu=0; Section 12 takes this difference apart.

三个右端项

The three right-hand sides

右端 −RD ek-R_D\,e_k 同样由前向代码算出:取 𝐔˙=0\dot{\mathbf U}=0、D˙=ek\dot D=e_k,返回的 R˙\dot R 就是 RDekR_De_k。代码里只有三处读取设计,所以右端只有三条路径:

The right-hand side −RD ek-R_D\,e_k comes from the tangent code as well: with 𝐔˙=0\dot{\mathbf U}=0 and D˙=ek\dot D=e_k the returned R˙\dot R is RDekR_De_k. Only three places of the code read the design, so the right-hand side has three paths:

  • 约束行(a,φa,\varphi):R0=U0−uinR_0=U_0-u_{\rm in}、RN=UN−uoutR_N=U_N-u_{\rm out},其中 uin=uout=1−a sin⁡ 2πφu_{\rm in}=u_{\rm out}=1-a\,\sin\,2\pi\varphi。边界值只出现在这两行里(每个面两侧都有节点,面通量不读边界值),所以右端的第一项与最后一项就是边界数据的导数 ∂uin/∂Dk\partial u_{\rm in}/\partial D_k、∂uout/∂Dk\partial u_{\rm out}/\partial D_k。它们不随 hh 变小,也不随 hh 变大。The constraint rows (a,φa,\varphi): R0=U0−uinR_0=U_0-u_{\rm in} and RN=UN−uoutR_N=U_N-u_{\rm out} with uin=uout=1−a sin⁡ 2πφu_{\rm in}=u_{\rm out}=1-a\,\sin\,2\pi\varphi. The boundary values occur only in these two rows (every face has a node on both sides, so no face flux reads a boundary value): the first and the last entry of the right-hand side are the derivatives ∂uin/∂Dk\partial u_{\rm in}/\partial D_k and ∂uout/∂Dk\partial u_{\rm out}/\partial D_k of the boundary data themselves. They neither shrink nor grow with hh.
  • 源项行(a,φ,νa,\varphi,\nu):第 1,…,N−11,\dots,N-1 行有 −(Q˙j−Q˙j−1)-(\dot Q_j-\dot Q_{j-1}),即精确通量 Qf=q∗(xf+1/2;D)Q_f=q^*(x_{f+1/2};D) 的变化。它是源项导数在一个对偶控制体上的积分,大小约与 hh 成正比。The source rows (a,φ,νa,\varphi,\nu): rows 1,…,N−11,\dots,N-1 have −(Q˙j−Q˙j−1)-(\dot Q_j-\dot Q_{j-1}), the change of the exact flux Qf=q∗(xf+1/2;D)Q_f=q^*(x_{f+1/2};D). It is the integral of a derivative of the source over one dual volume, of a size proportional to hh.
  • 通量本身(只有 ν\nu):每个面的黏性通量 −ν(Uf+1−Uf)/h-\nu(U_{f+1}-U_f)/h 显含 ν\nu,偏导 −(Uf+1−Uf)/h-(U_{f+1}-U_f)/h 分发到面两侧的两行(只进入内部行)。The flux itself (ν\nu only): the viscous flux −ν(Uf+1−Uf)/h-\nu(U_{f+1}-U_f)/h of every face contains ν\nu explicitly; its partial derivative −(Uf+1−Uf)/h-(U_{f+1}-U_f)/h is scattered to the two rows beside the face (only interior rows receive it).

因为第 00 行和第 NN 行是单位行,方程组可以先消去它们:vk,0v_{k,0}、vk,Nv_{k,N} 已知,内部节点解 AIIvI=−(RD)Iek−AI0vk,0−AINvk,NA_{II}v_I=-(R_D)_Ie_k-A_{I0}v_{k,0}-A_{IN}v_{k,N}。边界值经 AA 的第 00 列和第 NN 列进入内部(这两列在第 11、22 行及第 N−2N-2、N−1N-1 行有非零元;一阶格式只在第 11 行和第 N−1N-1 行):边界数据对内部来说就是一份额外的源项。

Since rows 00 and NN are identity rows, the system can be reduced first: vk,0v_{k,0} and vk,Nv_{k,N} are known, and the interior nodes solve AIIvI=−(RD)Iek−AI0vk,0−AINvk,NA_{II}v_I=-(R_D)_Ie_k-A_{I0}v_{k,0}-A_{IN}v_{k,N}. The boundary values enter the interior through columns 00 and NN of AA (which have nonzero entries in rows 11 and 22 and in rows N−2N-2 and N−1N-1; only in rows 11 and N−1N-1 at first order): to the interior, the boundary data are one more source term.

图 46 · 三个右端项 -R_De_k(默认设计,无限制器线性)。上排 N=8,下排 N=64,每列共用纵轴。a、φ、ν 三列的内部行(绿)是对偶控制体上的积分,网格加密 8 倍后最大值分别缩小为原来的 1/7.7、1/7.2 与 1/24(ν 列里通量部分与源项部分在内部几乎抵消);首末两行(紫,只有 a、φ 两列)是边界数据的导数,不随网格改变:第一行恒为 −0.4258(a)与 −1.1370(φ)。−0.500.500.51x−RD​ ek​k = 0:振幅 a,N = 8−1−0.500.5100.51xk = 1:相位 φ,N = 8−0.3−0.2−0.100.100.51xk = 2:黏性 ν,N = 8−0.500.500.51x−RD​ ek​N = 64−1−0.500.5100.51xN = 64−0.3−0.2−0.100.100.51xN = 64
图 46 · 三个右端项 −RDek-R_De_k(默认设计,无限制器线性)。上排 N=8N=8,下排 N=64N=64,每列共用纵轴。aa、φ\varphi、ν\nu 三列的内部行(绿)是对偶控制体上的积分,网格加密 8 倍后最大值分别缩小为原来的 1/7.7、1/7.2 与 1/24(ν\nu 列里通量部分与源项部分在内部几乎抵消);首末两行(紫,只有 aa、φ\varphi 两列)是边界数据的导数,不随网格改变:第一行恒为 −0.4258−0.4258(aa)与 −1.1370−1.1370(φ\varphi)。
Figure 46 · The three right-hand sides -R_De_k (default design, unlimited linear). Top row N=8, bottom row N=64; each column shares its vertical axis. The interior rows (green) are integrals over a dual volume; under eightfold refinement their largest entry shrinks by a factor of 7.7, 7.2 and 24 for a, φ and ν (in the ν column the flux part and the source part nearly cancel inside). The first and the last row (violet; only the a and φ columns) are the derivatives of the boundary data and do not change with the mesh: the first entry is −0.4258 (a) and −1.1370 (φ) at every N.−0.500.500.51x−RD​ ek​k = 0: amplitude a, N = 8−1−0.500.5100.51xk = 1: phase φ, N = 8−0.3−0.2−0.100.100.51xk = 2: viscosity ν, N = 8−0.500.500.51x−RD​ ek​N = 64−1−0.500.5100.51xN = 64−0.3−0.2−0.100.100.51xN = 64
Figure 46 · The three right-hand sides −RDek-R_De_k (default design, unlimited linear). Top row N=8N=8, bottom row N=64N=64; each column shares its vertical axis. The interior rows (green) are integrals over a dual volume; under eightfold refinement their largest entry shrinks by a factor of 7.7, 7.2 and 24 for aa, φ\varphi and ν\nu (in the ν\nu column the flux part and the source part nearly cancel inside). The first and the last row (violet; only the aa and φ\varphi columns) are the derivatives of the boundary data and do not change with the mesh: the first entry is −0.4258−0.4258 (aa) and −1.1370−1.1370 (φ\varphi) at every NN.

为什么首末两行较大的右端项会影响整个解?vk=A−1(−RDek)v_k=A^{-1}(-R_De_k) 是一个叠加:右端项的第 jj 个分量就像加在第 jj 行上的一个量,A−1A^{-1} 的第 jj 列是状态对它的响应(Av=ejAv=e_j):内部行 jj 上是对偶控制体 jj 里多一份单位源项,第 00 行上是入口值多 11,第 NN 行上是出口值多 11。图 47 画出 N=16N=16 时的 A−1A^{-1}:源项几乎只向下游(矩阵对角线以下、剖面的右侧)改变状态——第 5 行的单位量使下游各内部节点变化 0.63–1.31,上游各节点最多变化 0.042(节点 5 自身变化的 6.6%);靠近出口时响应回落,到出口节点恰为零,因为 uoutu_{\rm out} 是给定的。所以第一行的右端项(入口值)影响整个区间,最后一行的右端项只影响出口附近。

Why do the large first and last right-hand-side entries affect the whole solution? vk=A−1(−RDek)v_k=A^{-1}(-R_De_k) is a superposition: the jj-th entry of the right-hand side acts like a quantity added to row jj, and column jj of A−1A^{-1} is the response of the state to one unit in that row (Av=ejAv=e_j): in an interior row a unit of extra source in dual volume jj, in row 00 one more unit of inlet value, in row NN one more unit of outlet value. Figure 47 draws A−1A^{-1} for N=16N=16: a source changes the state mainly downstream (below the diagonal of the matrix, to the right in the profiles): a unit in row 5 moves the downstream interior nodes by 0.63–1.31 and the upstream nodes by at most 0.042 (6.6% of the node's own response); near the outlet the response falls back and is exactly zero at the outlet node, because uoutu_{\rm out} is prescribed. So the first right-hand-side entry (the inlet value) acts on the whole interval, the last one only near the outlet.

图 47 · 影响矩阵 A^(-1)(N=16,无限制器线性,默认设计;蓝正橙负)。左:(A^(-1))_ij 是第 j 行加一个单位量时 U_i 的变化(第 0 列:入口值加 1);右:第 0、5、10 列的剖面。u>0,信息向下游传播,上游各节点变化小得多:单位量在第 3–10 行时,上游的最大变化是该节点自身变化的 6–8%;越靠近两端,这个比例越大(最多 26%)。两个边界节点对内部行上的单位量没有响应(它们的行是约束行),第 0 列与第 N 列自身在各自的边界节点上是 1。用同一个矩阵解释伴随:-ψ_j=w^TA^(-1)e_j 就是第 j 列按目标权重的和,对包括 0 与 N 在内的每一个 j 成立(数值上相差不到 10^(-15))。04812160481216A−1​第 j 列:第 j 行加单位量时的响应列 j(加单位量的行)行 i(响应的节点)00.20.40.60.811.21.400.250.50.751x三列的剖面:单位量向下游传播j = 0j = 5j = 10
图 47 · 影响矩阵 A−1A^{-1}(N=16N=16,无限制器线性,默认设计;蓝正橙负)。左:(A−1)ij(A^{-1})_{ij} 是第 jj 行加一个单位量时 UiU_i 的变化(第 00 列:入口值加 11);右:第 0、5、10 列的剖面。u>0u>0,信息向下游传播,上游各节点变化小得多:单位量在第 3–10 行时,上游的最大变化是该节点自身变化的 6–8%;越靠近两端,这个比例越大(最多 26%)。两个边界节点对内部行上的单位量没有响应(它们的行是约束行),第 00 列与第 NN 列自身在各自的边界节点上是 11。第 11 节用同一个矩阵解释伴随:−ψj=wTA−1ej-\psi_j=w^TA^{-1}e_j 就是第 jj 列按目标权重的和,对包括 00 与 NN 在内的每一个 jj 成立(数值上相差不到 10−1510^{-15})。
Figure 47 · The influence matrix A^(-1) (N=16, unlimited linear, default design; blue positive, orange negative). Left: (A^(-1))_ij is the change of U_i when row j receives one unit (column 0: one more unit of inlet value); right: columns 0, 5 and 10 as profiles. Information travels downstream with u>0; the upstream nodes change much less: by 6–8% of the node's own response for a unit in rows 3–10, more towards both ends (up to 26%). The two boundary nodes never respond to a unit in an interior row (the constraint rows), and columns 0 and N are 1 at their own boundary node. uses the same matrix to explain the adjoint: -ψ_j=w^TA^(-1)e_j is the objective-weighted sum of column j, for every j from 0 to N (numerically within 10^(-15)).04812160481216A−1​column j: response to a unit added to row jcolumn j (row that receives the unit)row i (responding node)00.20.40.60.811.21.400.250.50.751xthree columns as profiles: a unit acts downstreamj = 0j = 5j = 10
Figure 47 · The influence matrix A−1A^{-1} (N=16N=16, unlimited linear, default design; blue positive, orange negative). Left: (A−1)ij(A^{-1})_{ij} is the change of UiU_i when row jj receives one unit (column 00: one more unit of inlet value); right: columns 0, 5 and 10 as profiles. Information travels downstream with u>0u>0; the upstream nodes change much less: by 6–8% of the node's own response for a unit in rows 3–10, more towards both ends (up to 26%). The two boundary nodes never respond to a unit in an interior row (the constraint rows), and columns 00 and NN are 11 at their own boundary node. Section 11 uses the same matrix to explain the adjoint: −ψj=wTA−1ej-\psi_j=w^TA^{-1}e_j is the objective-weighted sum of column jj, for every jj from 00 to NN (numerically within 10−1510^{-15}).

第 12 节把每一列拆成这些路径,并跟踪每条路径对梯度的贡献。下面的面板对当前设计做完整的前向求解,并用两次完整的非线性重解检查 vkv_k:中心差商 (𝐔(D+τek)−𝐔(D−τek))/(2τ)(\mathbf U(D+\tau e_k)-\mathbf U(D-\tau e_k))/(2\tau),步长取 τ=1×10−6\tau=1\times10^{-6},这个值本身并无特别之处。默认设计下三种重构、三个分量的最大差低于 10−910^{-9}(第 13 节研究步长的选择)。

Section 12 splits every column into these paths and follows each into the gradient. The panel below performs the whole tangent solve for the current design and checks vkv_k against two full nonlinear re-solves: the central difference (𝐔(D+τek)−𝐔(D−τek))/(2τ)(\mathbf U(D+\tau e_k)-\mathbf U(D-\tau e_k))/(2\tau), where the step τ=1×10−6\tau=1\times10^{-6} is just a number. At the default design the largest difference over the three reconstructions and the three components is below 10−910^{-9} (Section 13 studies the choice of the step).

“切线”的含义:扰动后重新求解

What “tangent” means: perturb and re-solve

切线解是一个预测:对很小的 tt,𝐔(D+t ek)≈𝐔+t vk\mathbf U(D+t\,e_k)\approx\mathbf U+t\,v_k。验证它只需要非线性求解器本身:在 D+t ekD+t\,e_k 上重新完整求解,再与预测比较。残差是 𝐔\mathbf U 与 DD 的光滑函数,AA 非奇异,所以 𝐔(D)\mathbf U(D) 光滑(隐函数定理),余项是二阶的:

The tangent solution is a prediction: for small tt, 𝐔(D+t ek)≈𝐔+t vk\mathbf U(D+t\,e_k)\approx\mathbf U+t\,v_k. Checking it needs nothing but the nonlinear solver: solve the full equations again at D+t ekD+t\,e_k and compare with the prediction. The residual is a smooth function of 𝐔\mathbf U and DD and AA is nonsingular, so 𝐔(D)\mathbf U(D) is smooth (implicit function theorem) and the remainder is of second order:

𝐔(D+t ek)=𝐔(D)+t vk+O(t2).\mathbf U(D+t\,e_k)=\mathbf U(D)+t\,v_k+O(t^2).

tt 很小时,把 tt 减半,误差约变为原来的四分之一(在本页测试的范围内,相邻两个步长的误差之比在 3.82–4.18 之间)。默认设计(N=8N=8,无限制器线性)下,在 ∣t∣≤0.15|t|\le0.15(aa)、∣t∣≤0.25|t|\le0.25(φ\varphi)、∣t∣≤0.008|t|\le0.008(ν\nu)范围内,比值 ∥𝐔(D+t ek)−𝐔−t vk∥∞/t2\|\mathbf U(D+t\,e_k)-\mathbf U-t\,v_k\|_\infty/t^2 分别停留在 0.049–0.053、3.60–3.91、1.80–2.00:在双对数图里误差曲线的斜率接近 2,这就是“切线”的标志。在面板里选一个节点、一个步长;其后的播放器把整条剖面做成动画。

For small tt, halving tt divides the error by about four (by 3.82–4.18 in the range tested here). At the default design (N=8N=8, unlimited linear), for ∣t∣≤0.15|t|\le0.15 (aa), ∣t∣≤0.25|t|\le0.25 (φ\varphi) and ∣t∣≤0.008|t|\le0.008 (ν\nu), the ratio ∥𝐔(D+t ek)−𝐔−t vk∥∞/t2\|\mathbf U(D+t\,e_k)-\mathbf U-t\,v_k\|_\infty/t^2 stays within 0.049–0.053, 3.60–3.91 and 1.80–2.00 respectively: on log–log axes the error curve has a slope close to 2, the signature of a tangent. Pick a node and a step in the panel; the player after it animates the whole profile.

切线只在 tt 很小时才可靠:沿 φ\varphi 走 t=0.25t=0.25(四分之一个周期)时,预测与重解相差 0.2330.233。导数描述无穷小变化的响应;大步长的优化器必须重新求解。另一个常见错误是在未收敛的状态上求导:只有在 R(𝐔,D)=0R(\mathbf U,D)=0 处,Avk=−RDekAv_k=-R_De_k 才是解的导数;Newton 迭代中途的 AA 给出的是另一个函数的切线。

The tangent line is reliable only for small tt: a step t=0.25t=0.25 in φ\varphi (a quarter of the period) misses the re-solved state by 0.2330.233. A derivative describes the response to an infinitesimal change; an optimiser that takes large steps must re-solve. Another common slip is to differentiate at a state that has not converged: only where R(𝐔,D)=0R(\mathbf U,D)=0 is Avk=−RDekAv_k=-R_De_k the derivative of the solution; the AA of an intermediate Newton iterate gives the tangent of a different function.

连续切线问题

The continuous tangent

对第 1 节的连续问题用同样的方法求导,得到连续切线方程。记 uDk=∂u/∂Dku_{D_k}=\partial u/\partial D_k。对 Dk=a,φD_k=a,\varphi,只有源项与两端的给定值依赖 DkD_k;对 ν\nu,通量 q=u2/2−νuxq=u^2/2-\nu u_x 本身含 ν\nu,于是右端多出 uxxu_{xx}:

Differentiating the continuous problem of Section 1 in the same way gives the continuous tangent equations. Write uDk=∂u/∂Dku_{D_k}=\partial u/\partial D_k. For Dk=a,φD_k=a,\varphi only the source and the two end values depend on DkD_k; for ν\nu the flux q=u2/2−νuxq=u^2/2-\nu u_x contains ν\nu itself, which adds uxxu_{xx} to the right-hand side:

(u uDk−ν (uDk)x)x=sDk,uDk(0)=∂uin∂Dk,uDk(1)=∂uout∂Dk(Dk=a,φ),(u uν−ν (uν)x)x=sν+uxx,uν(0)=uν(1)=0.\begin{aligned}&\bigl(u\,u_{D_k}-\nu\,(u_{D_k})_x\bigr)_x=s_{D_k},\qquad u_{D_k}(0)=\frac{\partial u_{\rm in}}{\partial D_k},\quad u_{D_k}(1)=\frac{\partial u_{\rm out}}{\partial D_k}\qquad(D_k=a,\varphi),\\&\bigl(u\,u_\nu-\nu\,(u_\nu)_x\bigr)_x=s_\nu+u_{xx},\qquad u_\nu(0)=u_\nu(1)=0.\end{aligned}

对构造解不需要求解:u∗u^* 对每个设计都是解,所以它对设计的导数就是切线问题的解:ua∗=sin⁡ zu^*_a=\sin\,z,uφ∗=−2πa cos⁡ zu^*_\varphi=-2\pi a\,\cos\,z,uν∗=0u^*_\nu=0(解与 ν\nu 无关;事实上 sν=4π2a sin⁡ z=−uxx∗s_\nu=4\pi^2a\,\sin\,z=-u^*_{xx},右端为零)。这三个函数与格式无关。本页用一个独立的 Chebyshev 配点求解器(M=64M=64)解前两个边值问题,与 ua∗u^*_a、uφ∗u^*_\varphi 的闭式相差不到 10−1310^{-13};ν\nu 的问题右端与边界值都恒为零,解自然是零,这一项检验是平凡的。离散的 vkv_k 是节点上的点值,与这些函数在节点上的值 ua∗(xj)=sin⁡ zju^*_a(x_j)=\sin\,z_j、uφ∗(xj)=−2πa cos⁡ zju^*_\varphi(x_j)=-2\pi a\,\cos\,z_j、uν∗(xj)=0u^*_\nu(x_j)=0 比较(本页的未知量是点值,所以不需要像格心页那样乘一个 sinc\mathrm{sinc} 因子;两个边界节点上的差恰为零);图 48 与下表给出收敛情况。

For the manufactured solution no solve is needed: u∗u^* solves the problem for every design, so its derivative with respect to the design solves the tangent problem: ua∗=sin⁡ zu^*_a=\sin\,z, uφ∗=−2πa cos⁡ zu^*_\varphi=-2\pi a\,\cos\,z, uν∗=0u^*_\nu=0 (the solution does not depend on ν\nu; indeed sν=4π2a sin⁡ z=−uxx∗s_\nu=4\pi^2a\,\sin\,z=-u^*_{xx}, so the right-hand side vanishes). These three functions do not depend on the scheme. An independent Chebyshev collocation solver (M=64M=64) of the first two boundary-value problems reproduces the closed forms of ua∗u^*_a and uφ∗u^*_\varphi to within 10−1310^{-13}; for ν\nu the right-hand side and the boundary data vanish identically, so its zero solution is a trivial check. The discrete vkv_k are point values at the nodes and are compared with these functions at the nodes, ua∗(xj)=sin⁡ zju^*_a(x_j)=\sin\,z_j, uφ∗(xj)=−2πa cos⁡ zju^*_\varphi(x_j)=-2\pi a\,\cos\,z_j and uν∗(xj)=0u^*_\nu(x_j)=0 (the unknowns of this page are point values, so there is no sinc\mathrm{sinc} factor as on the cell-centred page; the difference at the two boundary nodes is exactly zero); Figure 48 and the table below show the convergence.

图 48 · 离散切线解向连续切线收敛(默认设计,无限制器线性)。N=8(圈)、32(点)、128(细线)的 v_k 与 ∂ u*/∂ D_k(粗线)。N=128 时 v_0,v_1 已与连续曲线重合;v_2 趋于零,但收敛最慢。连续:∂u*/∂Dk​N = 8N = 32N = 128−1−0.500.5100.51xvk​k = 0:振幅 a−1−0.500.511.500.51xk = 1:相位 φ−0.100.10.200.51xk = 2:黏性 ν
图 48 · 离散切线解向连续切线收敛(默认设计,无限制器线性)。N=8N=8(圈)、3232(点)、128128(细线)的 vkv_k 与 ∂u∗/∂Dk\partial u^*/\partial D_k(粗线)。N=128N=128 时 v0,v1v_0,v_1 已与连续曲线重合;v2v_2 趋于零,但收敛最慢。
Figure 48 · The discrete tangents converge to the continuous ones (default design, unlimited linear): v_k for N=8 (rings), 32 (dots) and 128 (thin line) against ∂ u*/∂ D_k (thick line). At N=128, v_0 and v_1 lie on the continuous curves; v_2 goes to zero, but most slowly.continuous: ∂u*/∂Dk​N = 8N = 32N = 128−1−0.500.5100.51xvk​k = 0: amplitude a−1−0.500.511.500.51xk = 1: phase φ−0.100.10.200.51xk = 2: viscosity ν
Figure 48 · The discrete tangents converge to the continuous ones (default design, unlimited linear): vkv_k for N=8N=8 (rings), 3232 (dots) and 128128 (thin line) against ∂u∗/∂Dk\partial u^*/\partial D_k (thick line). At N=128N=128, v0v_0 and v1v_1 lie on the continuous curves; v2v_2 goes to zero, but most slowly.
离散切线解与连续切线之间的最大差(无限制器线性):格点格式对节点上的精确值,格心格式(取自格心页)对它自己的未知量的精确值Largest difference between the discrete tangents and the continuous tangents (unlimited linear): node scheme against the nodal values, cell scheme (from the cell-centred page) against the exact values of its own unknowns
Nmax⁡j∣v0,j−ua∗(xj)∣\max_j|v_{0,j}-u^*_a(x_j)|max⁡j∣v1,j−uφ∗(xj)∣\max_j|v_{1,j}-u^*_\varphi(x_j)|max⁡j∣v2,j∣\max_j|v_{2,j}|格心:aacell: aa格心:φ\varphicell: φ\varphi格心:ν\nucell: ν\nu
81.4e−13.2e−11.9e−15.2e−13.4e−16.5e−1
329.6e−31.9e−26.5e−21.1e−15.0e−23.8e−1
1284.2e−46.0e−43.8e−32.0e−21.3e−22.1e−1
5122.0e−53.2e−58.9e−52.0e−31.6e−33.2e−2
20481.4e−62.4e−62.4e−61.5e−41.2e−42.7e−3
40963.5e−76.3e−77.6e−73.8e−53.2e−57.0e−4

无限制器线性重构时切线解的观测阶趋近 2(N=2048N=2048 到 40964096 之间为 1.98、1.96、1.66),一阶重构时趋近 1(1.00、1.00、1.01)——与状态本身的阶相同(第 15 节)。无限制器线性重构时,格点格式的切线比格心格式准得多:N=8N=8 时 v0v_0 与 v2v_2 的误差只有 0.26 与 0.29 倍(v1v_1 是 0.97 倍,并不更好),N=4096N=4096 时三个分量分别是格心格式的 9×10−39\times10^{-3}、2×10−22\times10^{-2}、1×10−31\times10^{-3} 倍(图 49)。N=4096N=4096 时格点格式的 v2v_2 仍是三者中最大的,但只是 v0v_0 误差的 2.2 倍(格心格式是 18 倍)。一阶重构时两种格式的切线误差相当(节点/格心:N=8N=8 时为 1.49、0.94、1.91,N=4096N=4096 时为 1.004、1.004、1.094)。

With unlimited linear reconstruction the observed orders of the tangents approach 2 (1.98, 1.96 and 1.66 between N=2048N=2048 and 40964096), with first-order reconstruction they approach 1 (1.00, 1.00, 1.01): the orders of the state itself (Section 15). With unlimited linear reconstruction the tangents of the node scheme are far more accurate than those of the cell scheme: at N=8N=8 the errors of v0v_0 and v2v_2 are 0.26 and 0.29 times the cell scheme's (that of v1v_1 is 0.97 times, no better), at N=4096N=4096 the three components are 9×10−39\times10^{-3}, 2×10−22\times10^{-2} and 1×10−31\times10^{-3} times theirs (Figure 49). At N=4096N=4096 the node scheme's v2v_2 is still the largest of the three, but only 2.2 times the error of v0v_0 (18 times on the cell page). With first-order reconstruction the two schemes have about the same tangent error (node/cell 1.49, 0.94, 1.91 at N=8N=8; 1.004, 1.004, 1.094 at N=4096N=4096).

图 49 · 切线解的误差随 N 的变化(默认设计),各自对它自己的未知量的精确值:格点格式的无限制器线性(绿点)与一阶重构(橙黄圈),格心格式(取自格心页)的无限制器线性(灰虚线)与一阶重构(紫色虚线方块)。无限制器线性重构时格点格式在每个网格上、每个分量都更小;两者误差之比先随 N 减小,v_0、v_1 的比值从 N=512 起基本不变(两种格式在那里都是二阶),v_2 的比值在 N=2048 最小;一阶重构时两种格式相当。格点,无限制器线性格点,一阶格心,无限制器线性格心,一阶10-7​10-6​10-5​10-4​10-3​10-2​10-1​1108645124096Nk = 0:振幅 a10-7​10-6​10-5​10-4​10-3​10-2​10-1​1108645124096Nk = 1:相位 φ10-7​10-6​10-5​10-4​10-3​10-2​10-1​1108645124096Nk = 2:黏性 ν
图 49 · 切线解的误差随 NN 的变化(默认设计),各自对它自己的未知量的精确值:格点格式的无限制器线性(绿点)与一阶重构(橙黄圈),格心格式(取自格心页)的无限制器线性(灰虚线)与一阶重构(紫色虚线方块)。无限制器线性重构时格点格式在每个网格上、每个分量都更小;两者误差之比先随 NN 减小,v0v_0、v1v_1 的比值从 N=512N=512 起基本不变(两种格式在那里都是二阶),v2v_2 的比值在 N=2048N=2048 最小;一阶重构时两种格式相当。
Figure 49 · The tangent errors against N (default design), each against the exact values of its own unknowns: node scheme with unlimited linear (green dots) and with first-order reconstruction (amber rings), cell scheme (from the cell-centred page) with unlimited linear (grey dashed) and with first-order reconstruction (violet dashed squares). With unlimited linear reconstruction the node scheme is smaller at every mesh and for every component. The ratio of the two errors falls at first and, for v_0 and v_1, stays nearly constant from N=512 on (both schemes are second order there); for v_2 it is smallest at N=2048; with first-order reconstruction the two schemes are about equal.node, unlimited linearnode, first ordercell, unlimited linearcell, first order10-7​10-6​10-5​10-4​10-3​10-2​10-1​1108645124096Nk = 0: amplitude a10-7​10-6​10-5​10-4​10-3​10-2​10-1​1108645124096Nk = 1: phase φ10-7​10-6​10-5​10-4​10-3​10-2​10-1​1108645124096Nk = 2: viscosity ν
Figure 49 · The tangent errors against NN (default design), each against the exact values of its own unknowns: node scheme with unlimited linear (green dots) and with first-order reconstruction (amber rings), cell scheme (from the cell-centred page) with unlimited linear (grey dashed) and with first-order reconstruction (violet dashed squares). With unlimited linear reconstruction the node scheme is smaller at every mesh and for every component. The ratio of the two errors falls at first and, for v0v_0 and v1v_1, stays nearly constant from N=512N=512 on (both schemes are second order there); for v2v_2 it is smallest at N=2048N=2048; with first-order reconstruction the two schemes are about equal.

代价:每个设计分量解一次

The cost: one solve per design component

每次前向求解回答一个问题:对一个设计方向的响应。设计有 nDn_D 个分量,就要用同一个矩阵 AA、nDn_D 个右端项解 nDn_D 次;这里 nD=3n_D=3。好处是,每次求解给出整个向量 vkv_k,于是状态的任何其他目标,导数只需再做一次内积。当目标少而设计分量多时,第 11 节把计算倒过来:用 ATA^T 解一次,就得到 dJh/dD\mathrm dJ_h/\mathrm dD 的全部分量(图 50)。

Each tangent solve answers one question: the response to one design direction. A design with nDn_D components needs nDn_D solves with the same matrix AA and nDn_D right-hand sides; here nD=3n_D=3. In return each solve gives the whole vector vkv_k, so the derivative of any other objective of the state is one more dot product. When the objectives are few and the design components many, Section 11 turns the computation around: one solve with ATA^T gives every component of dJh/dD\mathrm dJ_h/\mathrm dD at once (Figure 50).

图 50 · 两条路线(默认设计,N=8,无限制器线性)。上:前向路线,每个种子 D-dot=e_k 解一次 Av_k=-R_De_k,得到整个 v_k 和一个数 J-dot_k。下:伴随路线(),取 g=w,解一次 A^Tψ=-g,再做三个内积 ψ^TR_De_k。两条路线给出同样的三个数,相差不到 10^(-14)。前向路线(本节):每个设计分量解一次,共 nD​ = 3 次Ḋ = e0​A v0​ = −RD​ e0​v0​J̇0​ = wT​ v0​ = −0.178061Ḋ = e1​A v1​ = −RD​ e1​v1​J̇1​ = wT​ v1​ = 0.419904Ḋ = e2​A v2​ = −RD​ e2​v2​J̇2​ = wT​ v2​ = 0.003909伴随路线(第 11 节):一次转置求解,再做三个内积g = wAT​ ψ = −gψψT​ RD​ e0​ = −0.178061ψT​ RD​ e1​ = 0.419904ψT​ RD​ e2​ = 0.003909同样的三个数:两条路线相差不到 10-14​(N = 8,无限制器线性,默认设计)
图 50 · 两条路线(默认设计,N=8N=8,无限制器线性)。上:前向路线,每个种子 D˙=ek\dot D=e_k 解一次 Avk=−RDekAv_k=-R_De_k,得到整个 vkv_k 和一个数 J˙k\dot J_k。下:伴随路线(第 11 节),取 g=wg=w,解一次 ATψ=−gA^T\psi=-g,再做三个内积 ψTRDek\psi^TR_De_k。两条路线给出同样的三个数,相差不到 10−1410^{-14}。
Figure 50 · The two routes (default design, N=8, unlimited linear). Top: the tangent route solves Av_k=-R_De_k once per seed D-dot=e_k and obtains the whole v_k and one number J-dot_k. Bottom: the adjoint route () solves A^Tψ=-g once with g=w and then takes three dot products ψ^TR_De_k. Both give the same three numbers, less than 10^(-14) apart.tangent route (this section): one solve per design component, nD​ = 3 solvesḊ = e0​A v0​ = −RD​ e0​v0​J̇0​ = wT​ v0​ = −0.178061Ḋ = e1​A v1​ = −RD​ e1​v1​J̇1​ = wT​ v1​ = 0.419904Ḋ = e2​A v2​ = −RD​ e2​v2​J̇2​ = wT​ v2​ = 0.003909adjoint route (Section 11): one transposed solve, then three dot productsg = wAT​ ψ = −gψψT​ RD​ e0​ = −0.178061ψT​ RD​ e1​ = 0.419904ψT​ RD​ e2​ = 0.003909the same three numbers: the two routes differ by less than 10-14​ (N = 8, unlimited linear, default design)
Figure 50 · The two routes (default design, N=8N=8, unlimited linear). Top: the tangent route solves Avk=−RDekAv_k=-R_De_k once per seed D˙=ek\dot D=e_k and obtains the whole vkv_k and one number J˙k\dot J_k. Bottom: the adjoint route (Section 11) solves ATψ=−gA^T\psi=-g once with g=wg=w and then takes three dot products ψTRDek\psi^TR_De_k. Both give the same three numbers, less than 10−1410^{-14} apart.
第 11 节Section 11

伴随求解:一次转置求解得到全部梯度

The adjoint solve: one transposed solve for the whole gradient

本节实验:先预测 ψj\psi_j 是正还是负、∣ψj∣|\psi_j| 在哪里最大,在图 52 里核对;再看两个约束行的乘子 ψ0\psi_0、ψN\psi_N:连续伴随在两端是 λ(0)=λ(1)=0\lambda(0)=\lambda(1)=0,它们是什么?它们离连续伴随的哪个量最近?

Experiment: Predict first: is ψj\psi_j positive or negative, and where is ∣ψj∣|\psi_j| largest? Check it in Figure 52. Then look at the multipliers ψ0\psi_0 and ψN\psi_N of the two constraint rows: the continuous adjoint has λ(0)=λ(1)=0\lambda(0)=\lambda(1)=0 at the ends, so what are they, and which quantity of the continuous adjoint are they close to?

第 10 节每个设计分量要解一次线性方程组。只有一个目标而设计分量很多时,这样做很浪费:我们要的只是 nDn_D 个数 J˙k\dot J_k,而不是 nDn_D 个向量 vkv_k。本节把求解移到内积的另一侧。

Section 10 needed one linear solve per design component. With one objective and many design components that is wasteful: what we want are nDn_D numbers J˙k\dot J_k, not nDn_D vectors vkv_k. This section moves the solve to the other side of the dot product.

从 nDn_D 次前向求解到一次转置求解

From nDn_D tangent solves to one transposed solve

对任意种子 D˙\dot D,前向求解给出 v=−A−1RDD˙v=-A^{-1}R_D\dot D,目标的方向导数是 J˙=wTv\dot J=w^Tv。把前者代入后者,从左边把因子合并:

For any seed D˙\dot D the tangent solve gives v=−A−1RDD˙v=-A^{-1}R_D\dot D, and the directional derivative of the objective is J˙=wTv\dot J=w^Tv. Insert the first into the second and group the factors from the left:

J˙=wTv=−wTA−1RD D˙=(−A−Tw)TRD D˙=ψTRD D˙,ATψ=−g,g=w.\dot J=w^Tv=-w^TA^{-1}R_D\,\dot D=\bigl(-A^{-T}w\bigr)^TR_D\,\dot D=\psi^TR_D\,\dot D,\qquad A^T\psi=-g,\quad g=w.

向量 ψ\psi(伴随)与 D˙\dot D 无关:用转置矩阵解一次,就对所有设计方向都适用。它有 N+1N+1 个分量,ψ1,…,ψN−1\psi_1,\dots,\psi_{N-1} 属于内部节点,ψ0\psi_0 与 ψN\psi_N 是两个约束行的乘子。梯度就是反向模式的设计伴随:

The vector ψ\psi, the adjoint, does not depend on D˙\dot D: one solve with the transposed matrix serves every design direction. It has N+1N+1 entries: ψ1,…,ψN−1\psi_1,\dots,\psi_{N-1} belong to the interior nodes, ψ0\psi_0 and ψN\psi_N are the multipliers of the two constraint rows. The gradient is the design adjoint of reverse mode:

Dˉ=RDTψ,dJhdDk=Dˉk=ψTRD ek=∑j=0Nψj (RD)jk.\bar D=R_D^T\psi,\qquad \frac{\mathrm dJ_h}{\mathrm dD_k}=\bar D_k=\psi^TR_D\,e_k=\sum_{j=0}^{N}\psi_j\,(R_D)_{jk}.

用第 9 节的话说:以 Rˉ=ψ\bar R=\psi 为种子运行反向代码,它返回 𝐔ˉ=ATψ\bar{\mathbf U}=A^T\psi(ψ\psi 满足伴随方程时正好等于 −g-g)和 Dˉ=RDTψ\bar D=R_D^T\psi,即梯度。第 9 节的对偶恒等式 RˉTR˙=𝐔ˉT𝐔˙+DˉTD˙\bar R^T\dot R=\bar{\mathbf U}^T\dot{\mathbf U}+\bar D^T\dot D 取 Rˉ=ψ\bar R=\psi、𝐔˙=vk\dot{\mathbf U}=v_k、D˙=ek\dot D=e_k(于是 R˙=0\dot R=0),就是 0=−gTvk+Dˉk0=-g^Tv_k+\bar D_k:前向与伴随给出同一个数。默认设计下,三种重构的反向代码返回的 𝐔ˉ\bar{\mathbf U} 都满足 ∥𝐔ˉ+w∥∞<10−15\|\bar{\mathbf U}+w\|_\infty<10^{-15};下表比较两条路线:

In the words of Section 9: run the reverse code with the seed Rˉ=ψ\bar R=\psi; it returns 𝐔ˉ=ATψ\bar{\mathbf U}=A^T\psi, which equals −g-g exactly when ψ\psi solves the adjoint equation, and Dˉ=RDTψ\bar D=R_D^T\psi, the gradient. The duality identity RˉTR˙=𝐔ˉT𝐔˙+DˉTD˙\bar R^T\dot R=\bar{\mathbf U}^T\dot{\mathbf U}+\bar D^T\dot D of Section 9 with Rˉ=ψ\bar R=\psi, 𝐔˙=vk\dot{\mathbf U}=v_k and D˙=ek\dot D=e_k (so that R˙=0\dot R=0) reads 0=−gTvk+Dˉk0=-g^Tv_k+\bar D_k: the tangent and the adjoint give the same number. At the default design the reverse code returns 𝐔ˉ\bar{\mathbf U} with ∥𝐔ˉ+w∥∞<10−15\|\bar{\mathbf U}+w\|_\infty<10^{-15} for each of the three reconstructions, and the table compares the two routes:

前向与伴随(N=8N=8,默认设计):最大差低于 10−1410^{-14},舍入误差的量级Tangent against adjoint (N=8N=8, default design): largest difference below 10−1410^{-14}, the size of round-off
重构Reconstructionkk前向 wTvkw^Tv_kTangent wTvkw^Tv_k伴随 ψTRDek\psi^TR_De_kAdjoint ψTRDek\psi^TR_De_k差Difference
一阶first order00−1.175176203765−1.175176203765−2.2e−16
一阶first order11−0.234593749400−0.234593749400−3.3e−16
一阶first order220.9925748669770.9925748669772.2e−16
无限制器线性unlimited linear00−0.178061153176−0.178061153176−5e−16
无限制器线性unlimited linear110.4199038734750.419903873475−1.4e−15
无限制器线性unlimited linear220.0039088428570.003908842857−2.8e−17
光滑限制器smooth limiter00−0.188210330105−0.1882103301058.3e−16
光滑限制器smooth limiter110.5534678233950.553467823395−5.6e−16
光滑限制器smooth limiter22−0.314999960484−0.314999960484−2.2e−16

右端的负号是一种约定:若写 ATψ=+gA^T\psi=+g,梯度就是 −ψTRD-\psi^TR_D。本页取 ATψ=−gA^T\psi=-g,使 Jh+ψTRJ_h+\psi^TR 与附录 A 的连续形式 J+∫λ (qx−s) dxJ+\int\lambda\,(q_x-s)\,\mathrm dx 符号一致:内部节点上 ψj\psi_j 与 λ(xj)\lambda(x_j) 同号,也不差一个因子 hh(RjR_j 是对偶控制体上的积分残差,wjw_j 里已经含有 hh):默认网格上 ψj/λ(xj)\psi_j/\lambda(x_j) 在内部节点取 0.82–1.21,N=64N=64 时在 j=8,16,32,48j=8,16,32,48 取 0.989–0.996。

The minus sign on the right-hand side is a convention: with ATψ=+gA^T\psi=+g the gradient would be −ψTRD-\psi^TR_D. This page keeps ATψ=−gA^T\psi=-g so that Jh+ψTRJ_h+\psi^TR and its continuous counterpart J+∫λ (qx−s) dxJ+\int\lambda\,(q_x-s)\,\mathrm dx of Appendix A carry the same sign: at the interior nodes ψj\psi_j and λ(xj)\lambda(x_j) have the same sign, and there is no factor hh between them (RjR_j is a residual integrated over a dual volume, and wjw_j already contains hh): on the default mesh ψj/λ(xj)\psi_j/\lambda(x_j) takes 0.82–1.21 at the interior nodes, and 0.989–0.996 at j=8,16,32,48j=8,16,32,48 for N=64N=64.

转置矩阵:倒着走的面循环

The transposed matrix: the face loop run backwards

ATA^T 是 AA 关于对角线的镜像:ATA^T 的第 jj 行是 AA 的第 jj 列,即未知量 UjU_j 进入的那些残差行。图 51 画出 N=8N=8 时的两者。反向代码从不形成转置矩阵(本页的直接求解为了方便确实形成并分解了 ATA^T;只有用 residual_b 的无矩阵路线从不形成它):第 9 节的反向面循环从最后一个面走到第一个面,给面 ff 种子 Hˉf\bar H_f(面 00 只给 −ψ1-\psi_1,面 ff 给 ψf−ψf+1\psi_f-\psi_{f+1},面 N−1N-1 只给 ψN−1\psi_{N-1}:它两侧内部节点的伴随之差),再把 cLHˉfc_L\bar H_f、cRHˉfc_R\bar H_f 和 ±κfHˉf\pm\kappa_f\bar H_f 送回这个面读过的节点。每个面送回的正是它在 AA 中各列的那几项,所以这个循环不形成矩阵就完成了与 ATA^T 的乘法。

ATA^T is AA mirrored about its diagonal: row jj of ATA^T is column jj of AA, the residual rows that the unknown UjU_j enters. Figure 51 shows both for N=8N=8. The reverse code never forms a transposed matrix (the page's direct solves do form and factor ATA^T, for convenience; only the matrix-free route through residual_b never forms it): the reverse face loop of Section 9 visits the faces from the last to the first and gives face ff the seed Hˉf\bar H_f (face 00 gets only −ψ1-\psi_1, face ff gets ψf−ψf+1\psi_f-\psi_{f+1}, face N−1N-1 gets only ψN−1\psi_{N-1}: the difference of the adjoints of the two interior nodes it separates), then sends cLHˉfc_L\bar H_f, cRHˉfc_R\bar H_f and ±κfHˉf\pm\kappa_f\bar H_f back to the nodes the face read. Each face sends back exactly its own entries of the columns of AA, so the loop applies ATA^T without forming it.

图 51 · 状态 Jacobian 与它的转置(N=8,无限制器线性,默认设计;蓝正橙负)。A 的第 j 行是残差 R_j 对至多 5 个未知量的导数(第 0 行与第 N 行是单位行,只有 1 个;第 1 行与第 N-1 行 4 个);A^T 的第 j 行是伴随方程 (A^Tψ)_j=-w_j 的系数,即 A 的第 j 列。0123456780123456781.00−1.101.37−0.240.110.39−1.941.69−0.190.100.40−1.971.62−0.230.110.39−1.911.58−0.330.130.37−1.811.58−0.430.140.36−1.711.63−0.470.150.35−1.691.55−0.151.000123456780123456781.00−1.100.391.37−1.940.40−0.241.69−1.970.390.11−0.191.62−1.910.370.10−0.231.58−1.810.360.11−0.331.58−1.710.350.13−0.431.63−1.690.14−0.471.550.15−0.151.00A = RU​(行 i:残差 Ri​;列 j:未知量 Uj​)AT​(行 j 收集 ψ:伴随方程的第 j 行)紫框:A 的第 3 列 = AT​ 的第 3 行,即 U3​ 进入的残差行第 0 行与第 8 行是约束的单位行:AT​ 的第 1 至 7 行不含 ψ0​ 与 ψ8​
图 51 · 状态 Jacobian 与它的转置(N=8N=8,无限制器线性,默认设计;蓝正橙负)。AA 的第 jj 行是残差 RjR_j 对至多 5 个未知量的导数(第 00 行与第 NN 行是单位行,只有 1 个;第 11 行与第 N−1N-1 行 4 个);ATA^T 的第 jj 行是伴随方程 (ATψ)j=−wj(A^T\psi)_j=-w_j 的系数,即 AA 的第 jj 列。
Figure 51 · The state Jacobian and its transpose (N=8, unlimited linear, default design; blue positive, orange negative). Row j of A holds the derivatives of the residual R_j with respect to at most 5 unknowns (rows 0 and N are identity rows with 1; rows 1 and N-1 have 4); row j of A^T holds the coefficients of the adjoint equation (A^Tψ)_j=-w_j, which are column j of A.0123456780123456781.00−1.101.37−0.240.110.39−1.941.69−0.190.100.40−1.971.62−0.230.110.39−1.911.58−0.330.130.37−1.811.58−0.430.140.36−1.711.63−0.470.150.35−1.691.55−0.151.000123456780123456781.00−1.100.391.37−1.940.40−0.241.69−1.970.390.11−0.191.62−1.910.370.10−0.231.58−1.810.360.11−0.331.58−1.710.350.13−0.431.63−1.690.14−0.471.550.15−0.151.00A = RU​ (row i: residual Ri​; column j: unknown Uj​)AT​ (row j collects ψ: row j of the adjoint equation)violet frame: column 3 of A = row 3 of AT​, the residual rows that U3​ entersrows 0 and 8 are the identity rows of the constraints: rows 1 to 7 of AT​ contain neither ψ0​ nor ψ8​
Figure 51 · The state Jacobian and its transpose (N=8N=8, unlimited linear, default design; blue positive, orange negative). Row jj of AA holds the derivatives of the residual RjR_j with respect to at most 5 unknowns (rows 00 and NN are identity rows with 1; rows 11 and N−1N-1 have 4); row jj of ATA^T holds the coefficients of the adjoint equation (ATψ)j=−wj(A^T\psi)_j=-w_j, which are column jj of AA.

转置也颠倒了信息传播的方向。看一阶格式(N=8N=8)的第 3 行:AA 的第 3 行是 (−1.601, 2.160, −0.673)(−1.601,\ 2.160,\ −0.673)(依次乘 U2,U3,U4U_2,U_3,U_4),上游的系数绝对值比下游的大:残差 R3R_3 主要取决于上游节点——u>0u>0 时原始问题的信息从左向右传。ATA^T 的第 3 行是 AA 的第 3 列 (−0.603, 2.160, −1.557)(−0.603,\ 2.160,\ −1.557)(依次乘 ψ2,ψ3,ψ4\psi_2,\psi_3,\psi_4),大系数换到了下游一侧:伴随从右向左传,从 x=1x=1 传向 x=0x=0。连续伴随方程 −uλx−νλxx=−(1+x)-u\lambda_x-\nu\lambda_{xx}=-(1+x)(附录 A)也是这样:它沿反方向输运,它的入口边界层(下文简称层)在 x=0x=0。

The transposition also reverses the direction in which information travels. Take row 3 of the first-order scheme (N=8N=8): row 3 of AA is (−1.601, 2.160, −0.673)(−1.601,\ 2.160,\ −0.673) (multiplying U2,U3,U4U_2,U_3,U_4); the upstream coefficient is larger in magnitude than the downstream one: the residual R3R_3 leans on the upstream node, and with u>0u>0 the information of the primal problem travels from left to right. Row 3 of ATA^T is column 3 of AA, (−0.603, 2.160, −1.557)(−0.603,\ 2.160,\ −1.557) (multiplying ψ2,ψ3,ψ4\psi_2,\psi_3,\psi_4): the large coefficient has moved to the downstream side, and the adjoint travels from right to left, from x=1x=1 towards x=0x=0. The continuous adjoint equation −uλx−νλxx=−(1+x)-u\lambda_x-\nu\lambda_{xx}=-(1+x) of Appendix A does the same: it transports in the reverse direction, and its inlet boundary layer (from here on: the layer) sits at x=0x=0.

第 00 行和第 NN 行还带来一个结构:它们是单位矩阵 II 的第 00 行与第 NN 行,A0j=I0jA_{0j}=I_{0j}、ANj=INjA_{Nj}=I_{Nj},所以伴随方程的第 1,…,N−11,\dots,N-1 行里没有 ψ0\psi_0 与 ψN\psi_N(对三种重构都精确为零)。内部节点的伴随 ψ1,…,ψN−1\psi_1,\dots,\psi_{N-1} 先由 AA 的内部块的转置单独决定;两个乘子随后由第 00 行和第 NN 行读出——它们是被动的。下一小节把这件事用在 ψ0\psi_0、ψN\psi_N 上。

Rows 00 and NN bring a structure of their own: they are rows 00 and NN of the identity matrix II, A0j=I0jA_{0j}=I_{0j} and ANj=INjA_{Nj}=I_{Nj}, so rows 1,…,N−11,\dots,N-1 of the adjoint equation contain neither ψ0\psi_0 nor ψN\psi_N (exactly zero for all three reconstructions). The interior adjoint ψ1,…,ψN−1\psi_1,\dots,\psi_{N-1} is determined first, by the transposed interior block of AA alone; the two multipliers are read off afterwards from rows 00 and NN: they are passive. The next subsections use this for ψ0\psi_0 and ψN\psi_N.

伴随场 ψ\psi

The adjoint field ψ\psi

图 52 是默认设计下的 ψ\psi。三种重构的 ψj\psi_j 在每个节点都为负(两个乘子也是);无限制器线性时内部节点上 ∣ψj∣|\psi_j| 在节点 1 最大(ψ1=−1.7095\psi_{1}=−1.7095),在节点 7 最小(ψ7=−0.2330\psi_{7}=−0.2330),ψN=−0.0870\psi_N=−0.0870 更小。实线是连续伴随 λ(x)\lambda(x)(附录 A,由独立的 Chebyshev 求解器算出):内部节点上 ψj≈λ(xj)\psi_j\approx\lambda(x_j),同号、无因子 hh。两端的 ψ0\psi_0、ψN\psi_N 不是场在 x=0,1x=0,1 的值——λ\lambda 在那里是零——而是约束行的乘子;它们在图右边单独画出。

Figure 52 shows ψ\psi at the default design. In all three reconstructions ψj\psi_j is negative at every node (the two multipliers included); with unlimited linear reconstruction ∣ψj∣|\psi_j| is largest at the interior node 1 (ψ1=−1.7095\psi_{1}=−1.7095) and smallest at node 7 (ψ7=−0.2330\psi_{7}=−0.2330), and ψN=−0.0870\psi_N=−0.0870 is smaller still. The solid line is the continuous adjoint λ(x)\lambda(x) of Appendix A (computed by an independent Chebyshev solver): at the interior nodes ψj≈λ(xj)\psi_j\approx\lambda(x_j), with the same sign and no factor hh. The end entries ψ0\psi_0 and ψN\psi_N are not the values of the field at x=0,1x=0,1 (there λ\lambda is zero) but the multipliers of the constraint rows; they are drawn separately on the right.

图 52 · 默认设计的伴随场(N=8):三种重构的 ψ_j(j=1,…,N-1)与连续伴随 λ(x)(实线;小圈是 λ(x_j))。λ 在 x=0 有一个宽约 ν/u_in ≈ 0.011 的层,λ_x(0)=−142.66;第一个内部节点 x_1=0.125 已在层外。右边两幅小图:约束行的乘子 ψ_0、ψ_N(三种重构)与连续伴随在两端的通量 νλ_x(0)=−1.4266、-νλ_x(1)=−0.0220(虚线)。连续伴随 λ(x)ψj​ 无限制器线性一阶光滑限制器边界通量−1.5−1−0.5000.20.40.60.81xψj​, λ(x)λx​(0) = −142.66:宽约 ν/uin​ 的层−1.5−1.45−1.4−1.35−1.3−1.25ψ0​(入口)−0.3−0.25−0.2−0.15−0.1−0.050ψN​(出口)
图 52 · 默认设计的伴随场(N=8N=8):三种重构的 ψj\psi_j(j=1,…,N−1j=1,\dots,N-1)与连续伴随 λ(x)\lambda(x)(实线;小圈是 λ(xj)\lambda(x_j))。λ\lambda 在 x=0x=0 有一个宽约 ν/uin≈0.011\nu/u_{\rm in}\approx0.011 的层,λx(0)=−142.66\lambda_x(0)=−142.66;第一个内部节点 x1=0.125x_1=0.125 已在层外。右边两幅小图:约束行的乘子 ψ0\psi_0、ψN\psi_N(三种重构)与连续伴随在两端的通量 νλx(0)=−1.4266\nu\lambda_x(0)=−1.4266、−νλx(1)=−0.0220-\nu\lambda_x(1)=−0.0220(虚线)。
Figure 52 · The adjoint field at the default design (N=8): ψ_j (j=1,…,N-1) of the three reconstructions and the continuous adjoint λ(x) (solid; the small rings are λ(x_j)). λ has a layer of width about ν/u_in ≈ 0.011 at x=0 with λ_x(0)=−142.66; the first interior node x_1=0.125 is already outside it. The two small panels on the right: the multipliers ψ_0 and ψ_N of the constraint rows (three reconstructions) and the fluxes of the continuous adjoint through the two ends, νλ_x(0)=−1.4266 and -νλ_x(1)=−0.0220 (dashed).continuous adjoint λ(x)ψj​ unlimited linearfirst ordersmooth limiterboundary flux−1.5−1−0.5000.20.40.60.81xψj​, λ(x)λx​(0) = −142.66: a layer of width ν/uin​−1.5−1.45−1.4−1.35−1.3−1.25ψ0​ (inlet)−0.3−0.25−0.2−0.15−0.1−0.050ψN​ (outlet)
Figure 52 · The adjoint field at the default design (N=8N=8): ψj\psi_j (j=1,…,N−1j=1,\dots,N-1) of the three reconstructions and the continuous adjoint λ(x)\lambda(x) (solid; the small rings are λ(xj)\lambda(x_j)). λ\lambda has a layer of width about ν/uin≈0.011\nu/u_{\rm in}\approx0.011 at x=0x=0 with λx(0)=−142.66\lambda_x(0)=−142.66; the first interior node x1=0.125x_1=0.125 is already outside it. The two small panels on the right: the multipliers ψ0\psi_0 and ψN\psi_N of the constraint rows (three reconstructions) and the fluxes of the continuous adjoint through the two ends, νλx(0)=−1.4266\nu\lambda_x(0)=−1.4266 and −νλx(1)=−0.0220-\nu\lambda_x(1)=−0.0220 (dashed).

ψj\psi_j 的含义:在一行里加一点量

What ψj\psi_j means: add a little to one row

给第 jj 行加上一个数:对内部行,这是给对偶控制体 jj 的积分源项加 tt——行 jj 变成 Rj−tR_j-t,其余行不变;对第 00 行,R0=U0−(uin+t)R_0=U_0-(u_{\rm in}+t) 就是把入口值加 tt,对第 NN 行是把出口值加 tt。前向种子 t˙=1\dot t=1 给出 R˙=Av−ej=0\dot R=Av-e_j=0,即 Av=ejAv=e_j;用伴随方程 ψT=−wTA−1\psi^T=-w^TA^{-1}:

Add a number tt to row jj: for an interior row this is tt more integrated source in dual volume jj, so row jj becomes Rj−tR_j-t and the other rows do not change; for row 00, R0=U0−(uin+t)R_0=U_0-(u_{\rm in}+t) is tt more inlet value, for row NN it is tt more outlet value. The forward seed t˙=1\dot t=1 gives R˙=Av−ej=0\dot R=Av-e_j=0, that is Av=ejAv=e_j, and with the adjoint equation, ψT=−wTA−1\psi^T=-w^TA^{-1}:

dJhdt=wTv=wTA−1ej=−ψTej=−ψj,j=0,…,N.\frac{\mathrm dJ_h}{\mathrm dt}=w^Tv=w^TA^{-1}e_j=-\psi^Te_j=-\psi_j,\qquad j=0,\dots,N.

所以 −ψj-\psi_j 是“第 jj 行多一个单位量时 JhJ_h 增加多少”。ψj<0\psi_j<0:任何一行加量都使 JhJ_h 增大。特别是 −ψ0=∂Jh/∂uin-\psi_0=\partial J_h/\partial u_{\rm in} 与 −ψN=∂Jh/∂uout-\psi_N=\partial J_h/\partial u_{\rm out} 是目标对两个边界值的导数(源项与另一个边界值不变):这就是乘子的意义。图 53 不用伴随直接测量这个关系:对每个 j=0,…,Nj=0,\dots,N 重新完整求解两次非线性方程(t=±10−5t=\pm10^{-5}),中心差商与 −ψj-\psi_j 的最大相对差为 2.3×10−102.3\times10^{-10}。加在节点 1、2 的源项影响最大:它们向下游影响几乎所有节点,而 JhJ_h 对整个区间加权求和;加在入口值上的影响 −ψ0-\psi_0 与它们同量级(入口值经整个区间向下游输运);加在出口值上的影响 −ψN-\psi_N 很小。

So −ψj-\psi_j is how much JhJ_h grows when row jj receives one more unit; ψj<0\psi_j<0 means that adding to any row raises JhJ_h. In particular −ψ0=∂Jh/∂uin-\psi_0=\partial J_h/\partial u_{\rm in} and −ψN=∂Jh/∂uout-\psi_N=\partial J_h/\partial u_{\rm out} are the derivatives of the objective with respect to the two boundary values (the source and the other boundary value fixed): that is what the multipliers mean. Figure 53 measures this relation without the adjoint: for every j=0,…,Nj=0,\dots,N it solves the full nonlinear equations twice (t=±10−5t=\pm10^{-5}), and the central difference agrees with −ψj-\psi_j to a relative 2.3×10−102.3\times10^{-10}. Sources in nodes 1 and 2 act most: they influence nearly every node downstream, and JhJ_h sums over the whole interval; a unit more inlet value acts with −ψ0-\psi_0, of the same order (the inlet value is transported downstream through the whole interval); a unit more outlet value acts with the small −ψN-\psi_N.

图 53 · ψ_j 的含义(N=8,无限制器线性)。柱:-ψ_j(紫:两个约束行,即入口值、出口值加量);圈:在第 j 行加量 t 后两次完整非线性重解得到的 dJ_h/ dt,不用伴随。两者的最大相对差 2.3 × 10^(-10),与这个步长下中心差商的截断与舍入误差同一量级。00.511.5200.51x柱:−ψj​(紫:约束行);圈:在第 j 行加单位量 t 后重新求解两次的中心差商 dJh​/dt(t = 1e−5)1.40611.70951.35141.05500.90840.72910.49550.23300.0870
图 53 · ψj\psi_j 的含义(N=8N=8,无限制器线性)。柱:−ψj-\psi_j(紫:两个约束行,即入口值、出口值加量);圈:在第 jj 行加量 tt 后两次完整非线性重解得到的 dJh/dt\mathrm dJ_h/\mathrm dt,不用伴随。两者的最大相对差 2.3×10−102.3\times10^{-10},与这个步长下中心差商的截断与舍入误差同一量级。
Figure 53 · What ψ_j means (N=8, unlimited linear). Bars: -ψ_j (violet: the two constraint rows, i.e. more inlet or outlet value); rings: dJ_h/ dt from two full nonlinear re-solves with an extra unit t in row j, without the adjoint. They agree to a relative 2.3 × 10^(-10), of the size expected from the truncation and round-off errors of a central difference with this step.00.511.5200.51xbars: −ψj​ (violet: constraint rows); rings: dJh​/dt from two full re-solves with an extra unit t in row j (t = 1e−5)1.40611.70951.35141.05500.90840.72910.49550.23300.0870
Figure 53 · What ψj\psi_j means (N=8N=8, unlimited linear). Bars: −ψj-\psi_j (violet: the two constraint rows, i.e. more inlet or outlet value); rings: dJh/dt\mathrm dJ_h/\mathrm dt from two full nonlinear re-solves with an extra unit tt in row jj, without the adjoint. They agree to a relative 2.3×10−102.3\times10^{-10}, of the size expected from the truncation and round-off errors of a central difference with this step.

图 47 的影响矩阵给出同一件事的另一种读法:−ψj=wTA−1ej-\psi_j=w^TA^{-1}e_j 是第 jj 列——第 jj 行加单位量在各节点引起的变化——按目标权重 wiw_i 加起来。切线解把扰动向下游送,伴随把下游的权重收集回来。在面板里换一行试试(第 00 行和第 NN 行也可以):

The influence matrix of Figure 47 gives a second reading of the same fact: −ψj=wTA−1ej-\psi_j=w^TA^{-1}e_j is column jj, the change that a unit in row jj causes in every node, summed with the objective weights wiw_i. The tangent sends a disturbance downstream; the adjoint gathers the downstream weights back. Try another row in the panel (rows 00 and NN included):

与连续伴随比较

Comparison with the continuous adjoint

在内部节点上,ψj\psi_j 逼近 λ(xj)\lambda(x_j)。离开入口层(xj>0.1x_j>0.1)的最大差见下表;观测阶趋近 2(最后三次网格加倍 512→1024→2048→4096 的观测阶为 1.93、1.96、1.98)。入口层本身(宽约 ν/uin\nu/u_{\rm in},N=8N=8 的一个网格间距是它的 11 倍)没有被分辨,图 54 的下排显示:N=8N=8 与 1616 时第一个内部节点已在层外,落在 λ\lambda 的平台上。第 16 节系统地研究这种一致性。

At the interior nodes ψj\psi_j approaches λ(xj)\lambda(x_j). The largest difference away from the inlet layer (xj>0.1x_j>0.1) is in the table below; the observed order approaches 2 (1.93, 1.96, 1.98 for the last three doublings of the mesh, 512→1024→2048→4096). The inlet layer itself (width about ν/uin\nu/u_{\rm in}; one mesh interval of N=8N=8 is 11 times as wide) is not resolved, and the bottom row of Figure 54 shows that at N=8N=8 and 1616 the first interior node already lies outside it, on the plateau of λ\lambda. Section 16 studies this consistency systematically.

图 54 · ψ_j 与 λ(无限制器线性,默认设计),N=8,16,32,64。上排:整个区间;下排:x[0,0.1] 的层,标题给出乘子 ψ_0(它是通量,不是 x=0 处的值)。网格加密时层外的点落到曲线上;N=8、16 时第一个内部节点(x_1=0.125、0.0625:距壁 11 与 5.7 个层宽)落在平台上;N=32(2.9 个层宽,λ 为外解值的 94%)与 N=64(1.4 个层宽,76%)时它落在层的侧翼上;层的形状没有被分辨,而 ψ_0 仍然准确(下一小节)。λ(x)ψj​(j = 1 … N−1)−1.5−1−0.5000.51xN = 8−1.5−1−0.5000.51xN = 16−1.5−1−0.5000.51xN = 32−1.5−1−0.5000.51xN = 64−1.5−1−0.5000.050.1xψ0​ = −1.406(通量)−1.5−1−0.5000.050.1xψ0​ = −1.401(通量)−1.5−1−0.5000.050.1xψ0​ = −1.414(通量)−1.5−1−0.5000.050.1xψ0​ = −1.421(通量)
图 54 · ψj\psi_j 与 λ\lambda(无限制器线性,默认设计),N=8,16,32,64N=8,16,32,64。上排:整个区间;下排:x∈[0,0.1]x\in[0,0.1] 的层,标题给出乘子 ψ0\psi_0(它是通量,不是 x=0x=0 处的值)。网格加密时层外的点落到曲线上;N=8N=8、1616 时第一个内部节点(x1=0.125x_1=0.125、0.06250.0625:距壁 11 与 5.7 个层宽)落在平台上;N=32N=32(2.9 个层宽,λ\lambda 为外解值的 94%)与 N=64N=64(1.4 个层宽,76%)时它落在层的侧翼上;层的形状没有被分辨,而 ψ0\psi_0 仍然准确(下一小节)。
Figure 54 · ψ_j against λ (unlimited linear, default design) for N=8,16,32,64. Top: the whole interval; bottom: the layer, x[0,0.1], with the multiplier ψ_0 in the title (it is a flux, not a value at x=0). Under refinement the points away from the layer settle on the curve; at N=8 and 16 the first interior node (x_1=0.125, 0.0625: 11 and 5.7 layer widths from the wall) lies on the plateau; at N=32 (2.9 widths, λ at 94% of its outer value) and N=64 (1.4 widths, 76%) it lies on the flank of the layer; the shape of the layer is not resolved, and ψ_0 is accurate nevertheless (next subsection).λ(x)ψj​ (j = 1 … N−1)−1.5−1−0.5000.51xN = 8−1.5−1−0.5000.51xN = 16−1.5−1−0.5000.51xN = 32−1.5−1−0.5000.51xN = 64−1.5−1−0.5000.050.1xψ0​ = −1.406 (a flux)−1.5−1−0.5000.050.1xψ0​ = −1.401 (a flux)−1.5−1−0.5000.050.1xψ0​ = −1.414 (a flux)−1.5−1−0.5000.050.1xψ0​ = −1.421 (a flux)
Figure 54 · ψj\psi_j against λ\lambda (unlimited linear, default design) for N=8,16,32,64N=8,16,32,64. Top: the whole interval; bottom: the layer, x∈[0,0.1]x\in[0,0.1], with the multiplier ψ0\psi_0 in the title (it is a flux, not a value at x=0x=0). Under refinement the points away from the layer settle on the curve; at N=8N=8 and 1616 the first interior node (x1=0.125x_1=0.125, 0.06250.0625: 11 and 5.7 layer widths from the wall) lies on the plateau; at N=32N=32 (2.9 widths, λ\lambda at 94% of its outer value) and N=64N=64 (1.4 widths, 76%) it lies on the flank of the layer; the shape of the layer is not resolved, and ψ0\psi_0 is accurate nevertheless (next subsection).
内部节点上与连续伴随的最大差(xj>0.1x_j>0.1;无限制器线性;带状求解器)Largest difference from the continuous adjoint at the interior nodes with xj>0.1x_j>0.1 (unlimited linear; banded solver)
Nmax⁡xj>0.1∣ψj−λ(xj)∣\max_{x_j>0.1}|\psi_j-\lambda(x_j)|
82.9e−1
161.3e−1
321.9e−2
646.1e−3
2566.3e−4
10244.6e−5
40963.0e−6

本页的新结果:约束行的乘子是连续伴随的边界通量

The new result of this page: the multipliers of the constraint rows are the boundary fluxes of the continuous adjoint

连续伴随在两端为零,梯度公式(附录 A、第 12 节)却含有它的导数:

The continuous adjoint vanishes at both ends, yet the gradient formula (Appendix A, Section 12) contains its derivative:

dJdDk=−∫01λ sDk dx+νλx(1) ∂uout∂Dk−νλx(0) ∂uin∂Dk.\frac{\mathrm dJ}{\mathrm dD_k}=-\int_0^1\lambda\,s_{D_k}\,\mathrm dx+\nu\lambda_x(1)\,\frac{\partial u_{\rm out}}{\partial D_k}-\nu\lambda_x(0)\,\frac{\partial u_{\rm in}}{\partial D_k}.

离散梯度(第 12 节)是

The discrete gradient (Section 12) is

dJhdDk=∑j=1N−1ψj(RD)jk−ψ0 ∂uin∂Dk−ψN ∂uout∂Dk.\frac{\mathrm dJ_h}{\mathrm dD_k}=\sum_{j=1}^{N-1}\psi_j(R_D)_{jk}-\psi_0\,\frac{\partial u_{\rm in}}{\partial D_k}-\psi_N\,\frac{\partial u_{\rm out}}{\partial D_k}.

逐项对照,边界项相符的条件是

Term by term, the boundary terms agree if

ψ0  ⟶  ν λx(0),ψN  ⟶  −ν λx(1)(N→∞):\psi_0\;\longrightarrow\;\nu\,\lambda_x(0),\qquad\psi_N\;\longrightarrow\;-\nu\,\lambda_x(1)\qquad(N\to\infty):

约束行的乘子是连续伴随在两端的(黏性)通量——λ\lambda 为零,所以对流部分没有贡献。这不是假设,是可以测量的:默认设计下 νλx(0)=−1.426568\nu\lambda_x(0)=−1.426568,−νλx(1)=−0.022035-\nu\lambda_x(1)=−0.022035(独立的 Chebyshev 求解器)。下表和图 55 给出无限制器线性重构下 ψ0\psi_0、ψN\psi_N 随网格加密的变化,并与格心页中对应的量 uˉin\bar u_{\rm in}、uˉout\bar u_{\rm out} 比较。

The multiplier of a constraint row is the (viscous) flux of the continuous adjoint through that end: λ\lambda is zero there, so the convective part does not contribute. This is not an assumption, it can be measured: at the default design νλx(0)=−1.426568\nu\lambda_x(0)=−1.426568 and −νλx(1)=−0.022035-\nu\lambda_x(1)=−0.022035 (independent Chebyshev solver). The table and Figure 55 show ψ0\psi_0 and ψN\psi_N under refinement for unlimited linear reconstruction, against the corresponding quantities uˉin\bar u_{\rm in} and uˉout\bar u_{\rm out} of the cell-centred page.

乘子 ψ0\psi_0、ψN\psi_N 与边界通量 νλx(0)=−1.4266\nu\lambda_x(0)=−1.4266、−νλx(1)=−0.0220-\nu\lambda_x(1)=−0.0220 的相对误差(无限制器线性;带状求解器);格心页的 uˉin\bar u_{\rm in}、uˉout\bar u_{\rm out} 对 −νλx(0)-\nu\lambda_x(0)、νλx(1)\nu\lambda_x(1) 的相对误差同列比较The multipliers ψ0\psi_0 and ψN\psi_N against the boundary fluxes νλx(0)=−1.4266\nu\lambda_x(0)=−1.4266 and −νλx(1)=−0.0220-\nu\lambda_x(1)=−0.0220: relative errors (unlimited linear; banded solver), with the relative errors of the cell page's uˉin\bar u_{\rm in}, uˉout\bar u_{\rm out} against −νλx(0)-\nu\lambda_x(0), νλx(1)\nu\lambda_x(1) beside them
Nψ0\psi_0相对误差relative error格心 uˉin\bar u_{\rm in} 的相对误差cell uˉin\bar u_{\rm in}: relative errorψN\psi_N相对误差relative error格心 uˉout\bar u_{\rm out} 的相对误差cell uˉout\bar u_{\rm out}: relative error
8−1.40608−1.4e−24.8e−2−0.087012.9e04.2e0
16−1.40116−1.8e−22.9e−2−0.051581.3e02.0e0
32−1.41357−9.1e−31.3e−2−0.035216.0e−19.9e−1
64−1.42122−3.7e−34.7e−3−0.027362.4e−14.4e−1
256−1.42599−4.1e−42.7e−4−0.022612.6e−26.0e−2
1024−1.42653−3.0e−56.6e−6−0.022081.9e−35.0e−3
4096−1.42657−1.9e−61.3e−7−0.022041.2e−43.4e−4

测量结果。入口:N=8N=8 时 ψ0=−1.4061\psi_0=−1.4061,与 νλx(0)\nu\lambda_x(0) 只差 1.4%——尽管入口层完全没有被分辨;相对误差随网格加密按二阶下降(最后三次网格加倍 512→1024→2048→4096 的观测阶 1.92、1.96、1.98);一阶重构时是一阶(1.00、1.00、1.00)。格心格式的 uˉin\bar u_{\rm in} 在 N=8N=8 时差 4.8%:格点格式在 N≤64N\le64 时更准,N≥128N\ge128 时格心格式的 uˉin\bar u_{\rm in} 反而更准(N=4096N=4096:1.3e−7 对 1.9e−6)。出口:N=8N=8 时 ψN=−0.0870\psi_N=−0.0870 是 −νλx(1)-\nu\lambda_x(1) 的 3.95 倍——相对误差很大,但绝对误差只有 0.065,而被逼近的通量 −νλx(1)-\nu\lambda_x(1) 本身只有 0.022;它同样按二阶收敛(1.93、1.96、1.98),N=64N=64 时差 24%,N=1024N=1024 时差 0.19%。格心格式的 uˉout\bar u_{\rm out} 在每个 NN 上都更差(N=8N=8 时是 −νλx(1)-\nu\lambda_x(1) 的 5.20 倍)。

The measurements. Inlet: at N=8N=8, ψ0=−1.4061\psi_0=−1.4061 is within 1.4% of νλx(0)\nu\lambda_x(0), although the inlet layer is not resolved at all; the relative error falls at second order under refinement (observed 1.92, 1.96, 1.98 for the last three doublings of the mesh, 512→1024→2048→4096), at first order for first-order reconstruction (1.00, 1.00, 1.00). The cell scheme's uˉin\bar u_{\rm in} is 4.8% off at N=8N=8: the node scheme is closer for N≤64N\le64, and from N=128N=128 on the cell scheme's uˉin\bar u_{\rm in} is the closer one (N=4096N=4096: 1.3e−7 against 1.9e−6). Outlet: at N=8N=8, ψN=−0.0870\psi_N=−0.0870 is 3.95 times −νλx(1)-\nu\lambda_x(1): a large relative error, but an absolute error of only 0.065, while the flux it approximates is only 0.022; it converges at second order too (1.93, 1.96, 1.98), and is 24% off at N=64N=64 and 0.19% at N=1024N=1024. The cell scheme's uˉout\bar u_{\rm out} is worse at every NN (5.20 times −νλx(1)-\nu\lambda_x(1) at N=8N=8).

图 55 · 乘子与边界通量的绝对误差随网格的变化(默认设计):格点格式的三种重构,以及格心格式的 u-bar_in、u-bar_out(灰虚线);点线是通量本身的大小,点落在它下面就说明相对误差小于 100%。入口乘子(左)从 N=8 起就远低于点线;出口的通量小两个量级,所以同样大小的绝对误差在这里就是很大的相对误差。格点格式:无限制器线性一阶光滑限制器格心格式 ūin​、ūout​点线:通量本身的大小10-7​10-6​10-5​10-4​10-3​10-2​10-1​1108645124096N入口:|ψ0​ − ν λx​(0)|10-6​10-5​10-4​10-3​10-2​10-1​18645124096N出口:|ψN​ + ν λx​(1)|
图 55 · 乘子与边界通量的绝对误差随网格的变化(默认设计):格点格式的三种重构,以及格心格式的 uˉin\bar u_{\rm in}、uˉout\bar u_{\rm out}(灰虚线);点线是通量本身的大小,点落在它下面就说明相对误差小于 100%。入口乘子(左)从 N=8N=8 起就远低于点线;出口的通量小两个量级,所以同样大小的绝对误差在这里就是很大的相对误差。
Figure 55 · Absolute errors of the multipliers against the boundary fluxes under refinement (default design): the three reconstructions of the node scheme, and u-bar_in, u-bar_out of the cell scheme (grey dashed); the dotted line is the size of the flux itself, a point below it means a relative error below 100%. The inlet multiplier (left) is far below the dotted line from N=8 on; the outlet flux is two orders of magnitude smaller, so an absolute error of the same size is a large relative error there.node: unlimited linearfirst ordersmooth limitercell scheme ūin​, ūout​dotted: size of the flux itself10-7​10-6​10-5​10-4​10-3​10-2​10-1​1108645124096Ninlet: |ψ0​ − ν λx​(0)|10-6​10-5​10-4​10-3​10-2​10-1​18645124096Noutlet: |ψN​ + ν λx​(1)|
Figure 55 · Absolute errors of the multipliers against the boundary fluxes under refinement (default design): the three reconstructions of the node scheme, and uˉin\bar u_{\rm in}, uˉout\bar u_{\rm out} of the cell scheme (grey dashed); the dotted line is the size of the flux itself, a point below it means a relative error below 100%. The inlet multiplier (left) is far below the dotted line from N=8N=8 on; the outlet flux is two orders of magnitude smaller, so an absolute error of the same size is a large relative error there.

层没被分辨时入口乘子为什么还准:一种解读

Why the inlet multiplier is accurate before the layer is resolved: a reading

乘子不是 ψ0/(h/2)\psi_0/(h/2) 那样的差商,而是伴随方程第 00 行(对 ψ0\psi_0 来说)直接给出的数。第 00 行是 ψ0+∑i≥1Ai0ψi=−w0\psi_0+\sum_{i\ge1}A_{i0}\psi_i=-w_0,只有第 11、22 行含 U0U_0,于是

The multiplier is not a difference quotient like ψ0/(h/2)\psi_0/(h/2) but the number that row 00 of the adjoint equation gives directly. Row 00 reads ψ0+∑i≥1Ai0ψi=−w0\psi_0+\sum_{i\ge1}A_{i0}\psi_i=-w_0, and only rows 11 and 22 contain U0U_0, so

ψ0=−w0−A10 ψ1−A20 ψ2,ψN=−wN−AN−1,N ψN−1−AN−2,N ψN−2.\psi_0=-w_0-A_{10}\,\psi_1-A_{20}\,\psi_2,\qquad\psi_N=-w_N-A_{N-1,N}\,\psi_{N-1}-A_{N-2,N}\,\psi_{N-2}.

乘子是紧邻边界的两个内部伴随值的加权和,权是边界附近面通量对边界值的灵敏度(对一阶格式第二项为零,只剩 ψ0=−w0+(cL(0)+κ) ψ1\psi_0=-w_0+(c_L(0)+\kappa)\,\psi_1:对流通量 (U0/2+1)ψ1(U_0/2+1)\psi_1 加上穿过第一个区间的黏性通量 νψ1/h\nu\psi_1/h)。下表在 N=8N=8 上算出三项:

The multiplier is a weighted sum of the two interior adjoint values next to the boundary, the weights being the sensitivities of the face fluxes there to the boundary value (at first order the second term is zero and only ψ0=−w0+(cL(0)+κ) ψ1\psi_0=-w_0+(c_L(0)+\kappa)\,\psi_1 remains: the convective flux (U0/2+1)ψ1(U_0/2+1)\psi_1 plus the viscous flux νψ1/h\nu\psi_1/h across the first interval). The table evaluates the three terms at N=8N=8:

两个约束行的伴随方程(N=8N=8,无限制器线性):三项之和就是乘子The adjoint equation of the two constraint rows (N=8N=8, unlimited linear): the three terms add up to the multiplier
行row−wj-w_j第一个通量项first flux term第二个通量项second flux termψ\psi
入口:ψ0=−w0−A10ψ1−A20ψ2\psi_0=-w_0-A_{10}\psi_1-A_{20}\psi_2inlet: ψ0=−w0−A10ψ1−A20ψ2\psi_0=-w_0-A_{10}\psi_1-A_{20}\psi_2−0.06250−1.873000.52943−1.40608
出口:ψN=−wN−AN−1,NψN−1−AN−2,NψN−2\psi_N=-w_N-A_{N-1,N}\psi_{N-1}-A_{N-2,N}\psi_{N-2}outlet: ψN=−wN−AN−1,NψN−1−AN−2,NψN−2\psi_N=-w_N-A_{N-1,N}\psi_{N-1}-A_{N-2,N}\psi_{N-2}−0.12500−0.035740.07373−0.08701

这个公式并没有解释 ψ0\psi_0 为什么准。在粗网格上,这两个内部值并不准确(N=8N=8 时 ψ1=−1.7095\psi_1=−1.7095,而 λ(x1)=−1.4158\lambda(x_1)=−1.4158,差 21%;ψ2\psi_2 差 5%)。把精确的 λ(x1)\lambda(x_1)、λ(x2)\lambda(x_2) 代入同一个公式得 −1.1105−1.1105,与 νλx(0)\nu\lambda_x(0) 差 22%,而用离散值得 −1.4061−1.4061,差 1.4%:ψ0\psi_0 的准确不是从 ψ1\psi_1、ψ2\psi_2 继承来的。下表对其他网格做同样的比较。

This formula does not explain why ψ0\psi_0 is accurate. On a coarse mesh the two interior values are not accurate (at N=8N=8: ψ1=−1.7095\psi_1=−1.7095 against λ(x1)=−1.4158\lambda(x_1)=−1.4158, 21% off; ψ2\psi_2 5% off). With the exact λ(x1)\lambda(x_1), λ(x2)\lambda(x_2) in place of ψ1\psi_1, ψ2\psi_2 the formula gives −1.1105−1.1105, 22% away from νλx(0)\nu\lambda_x(0), while the discrete values give −1.4061−1.4061, 1.4% away: the accuracy of ψ0\psi_0 is not inherited from ψ1\psi_1, ψ2\psi_2. The table makes the same comparison on other meshes.

第 00 行的公式 ψ0=−w0−A10ψ1−A20ψ2\psi_0=-w_0-A_{10}\psi_1-A_{20}\psi_2 分别用精确的 λ(x1)\lambda(x_1)、λ(x2)\lambda(x_2) 与离散的 ψ1\psi_1、ψ2\psi_2 计算(后者就是 ψ0\psi_0 本身):对 νλx(0)\nu\lambda_x(0) 的相对误差(无限制器线性;带状求解器)The row-0 formula ψ0=−w0−A10ψ1−A20ψ2\psi_0=-w_0-A_{10}\psi_1-A_{20}\psi_2 evaluated with the exact λ(x1)\lambda(x_1), λ(x2)\lambda(x_2) and with the discrete ψ1\psi_1, ψ2\psi_2 (the latter gives ψ0\psi_0 itself): relative errors against νλx(0)\nu\lambda_x(0) (unlimited linear; banded solver)
Nψ1/λ(x1)−1\psi_1/\lambda(x_1)-1ψ2/λ(x2)−1\psi_2/\lambda(x_2)-1精确 λ\lambda:ψ0\psi_0exact λ\lambda: ψ0\psi_0相对误差relative error离散 ψ\psi:ψ0\psi_0discrete ψ\psi: ψ0\psi_0相对误差relative error
82.1e−15.2e−2−1.1105−2.2e−1−1.4061−1.4e−2
161.5e−19.0e−2−1.1905−1.7e−1−1.4012−1.8e−2
327.5e−28.4e−2−1.3204−7.4e−2−1.4136−9.1e−3
644.2e−24.1e−2−1.3637−4.4e−2−1.4212−3.7e−3
2564.4e−21.6e−2−1.3584−4.8e−2−1.4260−4.1e−4

一种启发式读法(不是定理),说明 ψ0\psi_0 为什么不会差得很远、ψN\psi_N 又是什么:−ψ0=wTA−1e0-\psi_0=w^TA^{-1}e_0 是入口值多一个单位时按目标权重加起来的响应(第 10 节、图 47)。连续问题里这个响应是第 10 节的切线方程取边界值 11 与 00 的解,它的加权积分是 −νλx(0)=1.4266-\nu\lambda_x(0)=1.4266(用 Chebyshev 配点求解器核对);它沿区间光滑,唯一的层在出口,宽 ν/uin\nu/u_{\rm in}。这个层使加权总和减少约 2ν/uin=0.02192\nu/u_{\rm in}=0.0219(权重 1+x1+x 在出口等于 22),只占总和的 1.5%,所以一个没有分辨这个层的网格在 ψ0\psi_0 上至多差几个百分点(N=8N=8 时差 1.4%)。实测的误差并不跟着这个份额走:ν\nu 取 0.0020.002 到 0.020.02 的每个值,N=8N=8 时 ψ0\psi_0 的相对误差都在 1.4% 到 1.5% 之间,而层的份额从总和的 0.3% 增大到 3.1%(见下面的局限)。ψN\psi_N 是出口值多一个单位的响应:它就是这个出口层,加权大小约 2ν/uin=0.02192\nu/u_{\rm in}=0.0219,观测到的是 0.02200.0220;N=8N=8 没有分辨这个层,ψN\psi_N 差 295%。

A heuristic reading (not a theorem) of why ψ0\psi_0 cannot be far off and of what ψN\psi_N is: −ψ0=wTA−1e0-\psi_0=w^TA^{-1}e_0 is the weighted response to one more unit of inlet value (Section 10, Figure 47). In the continuous problem that response solves the tangent equation of Section 10 with the boundary values 11 and 00; its weighted integral is −νλx(0)=1.4266-\nu\lambda_x(0)=1.4266 (checked with a Chebyshev collocation solver), it is smooth along the interval, and its only layer is at the outlet, of width ν/uin\nu/u_{\rm in}. That layer lowers the weighted total by about 2ν/uin=0.02192\nu/u_{\rm in}=0.0219 (the weight 1+x1+x is 22 at the outlet), only 1.5% of the total, so a mesh that does not resolve it can be wrong in ψ0\psi_0 by a few percent at most (1.4% at N=8N=8). The observed error does not follow this deficit, though: for every ν\nu from 0.0020.002 to 0.020.02 the relative error of ψ0\psi_0 at N=8N=8 stays between 1.4% and 1.5%, while the deficit grows from 0.3% to 3.1% of the total (the limits are below). ψN\psi_N is the weighted response to one more unit of outlet value: it is that outlet layer, of weighted size about 2ν/uin=0.02192\nu/u_{\rm in}=0.0219 against the observed 0.02200.0220; N=8N=8 does not resolve it, and ψN\psi_N is 295% off.

连续问题里还有一个对应的事实:在层外,伴随方程的外解满足 λout(0)=−∫01(1+t)/u dt=−1.5619\lambda_{\rm out}(0)=-\int_0^1(1+t)/u\,\mathrm dt=−1.5619,而入口的通量在 ν\nu 的首阶近似下是 νλx(0)≈uinλout(0)=−1.4289\nu\lambda_x(0)\approx u_{\rm in}\lambda_{\rm out}(0)=−1.4289,与 νλx(0)=−1.4266\nu\lambda_x(0)=−1.4266 相近:入口的灵敏度等于层外伴随的对流通量。这些是启发式的解读;上面的测量才是证据,解读不是定理。

The continuous problem has a matching fact: outside the layer the outer solution of the adjoint equation has λout(0)=−∫01(1+t)/u dt=−1.5619\lambda_{\rm out}(0)=-\int_0^1(1+t)/u\,\mathrm dt=−1.5619, and to leading order in ν\nu the inlet flux is νλx(0)≈uinλout(0)=−1.4289\nu\lambda_x(0)\approx u_{\rm in}\lambda_{\rm out}(0)=−1.4289, close to νλx(0)=−1.4266\nu\lambda_x(0)=−1.4266: the sensitivity to the inlet value equals the convective flux of the adjoint outside the layer. These are heuristic readings; the measurements above are the evidence, and a reading is not a theorem.

与格心页对照:那里的乘子是半个单元里的量,要写成 ψ0/(h/2)\psi_0/(h/2) 才与 λx(0)\lambda_x(0) 相比,这个差商在 N=8N=8 时只有 −14.8−14.8,N=256N=256 时 −111.1−111.1,N=4096N=4096 时 −140.2−140.2(λx(0)=−142.7\lambda_x(0)=−142.7),到 N=2048N=2048 才与 λx(0)\lambda_x(0) 相差不到 5%;真正进入梯度的是组合 uˉin=−(cL(0)+2ν/h)ψ0\bar u_{\rm in}=-(c_L(0)+2\nu/h)\psi_0(N=8N=8 时差 4.8%)。本页没有半个单元,也没有这个组合:乘子就是进入梯度的量,N=8N=8 时差 1.4%。不要在任何一页上从粗网格的乘子读层的形状——它只告诉你通量。

Compare the cell page: there the multiplier lives in a half cell and has to be written as ψ0/(h/2)\psi_0/(h/2) to be compared with λx(0)\lambda_x(0); that quotient is only −14.8−14.8 at N=8N=8, −111.1−111.1 at N=256N=256 and −140.2−140.2 at N=4096N=4096 (λx(0)=−142.7\lambda_x(0)=−142.7), and comes within 5% of λx(0)\lambda_x(0) only from N=2048N=2048 on; what actually enters the gradient there is the combination uˉin=−(cL(0)+2ν/h)ψ0\bar u_{\rm in}=-(c_L(0)+2\nu/h)\psi_0 (4.8% off at N=8N=8). This page has no half cell and no combination: the multiplier is the quantity that enters the gradient, 1.4% off at N=8N=8. On neither page should you read the shape of the layer off a coarse-mesh multiplier: it tells you the flux.

局限:以上是默认设计下的数值观察,不是定理。把 ν\nu 从 0.0020.002 变到 0.10.1(层宽变化 50 倍),N=8N=8 时 ψ0\psi_0 的绝对误差只在 0.0205 到 0.0252 之间,ψN\psi_N 的绝对误差在 0.039 到 0.068 之间:层宽只要小于一个网格间距(这里的每个 ν\nu 都是),这两个误差的大小就差不多,层未被分辨时本该如此。这是粗网格上的效应,这些扫描无法把它分成层的部分与非层的部分。下面的面板可以改 NN、重构与 ν\nu:

The limits: these are numerical observations at the default design, not theorems. Changing ν\nu from 0.0020.002 to 0.10.1 (the layer width changes by a factor of 50) moves the absolute error of ψ0\psi_0 at N=8N=8 only between 0.0205 and 0.0252, and that of ψN\psi_N between 0.039 and 0.068: of the same order for every layer width below one interval (every ν\nu here), as expected when the layer is unresolved: a coarse-mesh effect that these sweeps cannot split into layer and non-layer parts. The panel below lets you change NN, the reconstruction and ν\nu:

组装梯度:谁的贡献

Assembling the gradient: who contributes

dJh/dDk=∑j=0Nψj(RD)jk\mathrm dJ_h/\mathrm dD_k=\sum_{j=0}^{N}\psi_j(R_D)_{jk} 是逐行的和。图 56 画出每一行的贡献 ψj(RD)jk\psi_j(R_D)_{jk} 和累加和,两个约束行单独着色。N=8N=8 时 aa 的梯度分成内部行的 0.45770.4577 与两个约束行的 −0.6357−0.6357,合计 −0.1781−0.1781;φ\varphi 的梯度是两个大数之差:内部行 2.11762.1176,约束行 −1.6977−1.6977,合计只有 0.41990.4199。ν\nu 的两个约束行不贡献(RDR_D 的 ν\nu 列在这两行为零)。与格心页不同,这里边界部分在每个网格上都恰好由首末两行承载:N=128N=128 时两部分是 0.47300.4730 与 −0.6168−0.6168(aa)、1.73251.7325 与 −1.6471−1.6471(φ\varphi)。梯度是 O(1)O(1) 的两部分之差,第 12 节把它们与连续梯度的两项一一对应。

dJh/dDk=∑j=0Nψj(RD)jk\mathrm dJ_h/\mathrm dD_k=\sum_{j=0}^{N}\psi_j(R_D)_{jk} is a sum over the rows. Figure 56 draws the contribution ψj(RD)jk\psi_j(R_D)_{jk} of every row and the running sum, with the two constraint rows coloured separately. At N=8N=8 the aa-gradient splits into 0.45770.4577 from the interior rows and −0.6357−0.6357 from the two constraint rows, together −0.1781−0.1781; the φ\varphi-gradient is the difference of two large numbers: 2.11762.1176 from the interior rows, −1.6977−1.6977 from the constraint rows, together only 0.41990.4199. The two constraint rows do not contribute to ν\nu (the ν\nu column of RDR_D is zero in those rows). Unlike on the cell page, the boundary part is carried by the first and the last row exactly, on every mesh: at N=128N=128 the two parts are 0.47300.4730 and −0.6168−0.6168 (aa), 1.73251.7325 and −1.6471−1.6471 (φ\varphi). The gradient is a difference of two parts of order one; Section 12 matches them with the two terms of the continuous gradient.

图 56 · 谁的贡献(N=8,无限制器线性,默认设计)。柱:每一行的贡献 ψ_j(R_D)_jk(紫:约束行);圆点:到该行为止的累加和;紫虚线:总和,即梯度分量 dJ_h/ dD_k。a 与 φ 的两个约束行贡献最大,但被内部行抵消了大半;ν 的约束行没有贡献。内部行 ψj​ (RD​)jk​约束行 0、N累加和总和 = 梯度−0.500.511.500.51xk = 0:振幅 adJh​/da = −0.1781−1.5−1−0.500.511.500.51xk = 1:相位 φdJh​/dφ = 0.4199−0.2−0.15−0.1−0.0500.050.100.51xk = 2:黏性 νdJh​/dν = 0.0039
图 56 · 谁的贡献(N=8N=8,无限制器线性,默认设计)。柱:每一行的贡献 ψj(RD)jk\psi_j(R_D)_{jk}(紫:约束行);圆点:到该行为止的累加和;紫虚线:总和,即梯度分量 dJh/dDk\mathrm dJ_h/\mathrm dD_k。aa 与 φ\varphi 的两个约束行贡献最大,但被内部行抵消了大半;ν\nu 的约束行没有贡献。
Figure 56 · Who contributes (N=8, unlimited linear, default design). Bars: the contribution ψ_j(R_D)_jk of each row (violet: the constraint rows); dots: the running sum up to that row; violet dashed line: the total, the gradient component dJ_h/ dD_k. For a and φ the two constraint rows contribute most, and the interior rows cancel most of it; for ν the constraint rows contribute nothing.interior rows ψj​ (RD​)jk​constraint rows 0, Nrunning sumtotal = gradient−0.500.511.500.51xk = 0: amplitude adJh​/da = −0.1781−1.5−1−0.500.511.500.51xk = 1: phase φdJh​/dφ = 0.4199−0.2−0.15−0.1−0.0500.050.100.51xk = 2: viscosity νdJh​/dν = 0.0039
Figure 56 · Who contributes (N=8N=8, unlimited linear, default design). Bars: the contribution ψj(RD)jk\psi_j(R_D)_{jk} of each row (violet: the constraint rows); dots: the running sum up to that row; violet dashed line: the total, the gradient component dJh/dDk\mathrm dJ_h/\mathrm dD_k. For aa and φ\varphi the two constraint rows contribute most, and the interior rows cancel most of it; for ν\nu the constraint rows contribute nothing.

下面的面板把本节的内容放在一起,网格、重构与黏性都可以改(带状求解器,NN 到 10241024):ψ\psi 与 λ\lambda、各行的贡献,以及梯度的四种算法——前向、伴随、两次完整重解的中心差商和连续问题的精确梯度。

The panel below puts this section together, with the mesh, the reconstruction and the viscosity of your choice (banded solver, NN up to 10241024): ψ\psi against λ\lambda, the contribution of each row, and the gradient by four routes: tangent, adjoint, central differences of two full re-solves, and the exact gradient of the continuous problem.

一次求解得到全部分量:代价

One solve for every component: the cost

两条路线的代价可以直接数。用不加预处理的 GMRES 解每个线性方程组,不形成矩阵,矩阵向量乘积只由代码给出:前向路线的每次迭代调用一次 residual_d(第 8 节),伴随路线的每次迭代调用一次 residual_b(第 9 节)。图 57 数出调用次数:设计只有 a,φ,νa,\varphi,\nu 三个分量时(nD=3n_D=3),前向路线的调用约是伴随路线的三倍;若再给每一行(包括两个约束行)一个源项分量(nD=N+4n_D=N+4,上面“ψj\psi_j 的含义”里的 tt),前向路线的调用随 NN 增长得快得多,而伴随路线的调用次数与 nDn_D 无关:N=64N=64 时是 3283 次对 64 次。a,φ,νa,\varphi,\nu 的求解与伴随求解每次约用 NN 次迭代(N=64N=64 时为 64、64、63、64),行源项的求解在较大的网格上用得少些(N=64N=64 时 31–64 次,均值 48),所以 nD=N+4n_D=N+4 时调用次数之比是 51,而不是 nD=68n_D=68。两条路线的梯度最大相差 2.3×10−122.3\times10^{-12}。与直接求解相比,这个差全在前向路线的行源项分量上(最多差 2.3×10−122.3\times10^{-12});两条路线的 a,φ,νa,\varphi,\nu 分量以及伴随路线的行分量与直接求解相差约 10−1410^{-14}(舍入误差)。

The cost of the two routes can be counted directly. Solve every linear system with unpreconditioned GMRES, without forming the matrix (the matrix–vector products come from the code): each iteration of the tangent route calls residual_d once (Section 8), each iteration of the adjoint route calls residual_b once (Section 9). Figure 57 counts the calls. With the three design components a,φ,νa,\varphi,\nu (nD=3n_D=3) the tangent route makes about three times as many calls as the adjoint route. Give every row (the two constraint rows included) one more source component as well (nD=N+4n_D=N+4, the tt of “What ψj\psi_j means” above), and the calls of the tangent route grow much faster with NN, while the calls of the adjoint route do not depend on nDn_D: 3283 calls against 64 at N=64N=64. The solves for a,φ,νa,\varphi,\nu and the adjoint solve take about NN iterations each (64, 64, 63, 64 at N=64N=64), while the solves for the extra row sources take fewer on the larger meshes (31–64, mean 48, at N=64N=64), so with nD=N+4n_D=N+4 the ratio of the calls is 51 rather than nD=68n_D=68. The gradients of the two routes differ by at most 2.3×10−122.3\times10^{-12}. Against a direct solve, all of it sits in the row-source components of the tangent route (off by up to 2.3×10−122.3\times10^{-12}); the components a,φ,νa,\varphi,\nu of both routes and the row components of the adjoint route agree with the direct solve to about 10−1410^{-14} (round-off).

图 57 · 两条路线的代价(无限制器线性,默认设计;纵轴为对数刻度):不加预处理的 GMRES 求解所调用的 residual_d(前向)与 residual_b(伴随)次数。a,φ,ν 与伴随的求解每次约用 N 次迭代,行源项的求解在较大网格上少一些。预处理()能减少每次求解的迭代次数,但前向路线仍要 n_D 次求解,伴随路线一次。110100103​104​23888N = 84730416N = 1695102832N = 32191328364N = 64前向或反向代码的调用次数前向路线,nD​ = 3前向路线,nD​ = N + 4伴随路线(两种 nD​ 相同)
图 57 · 两条路线的代价(无限制器线性,默认设计;纵轴为对数刻度):不加预处理的 GMRES 求解所调用的 residual_d(前向)与 residual_b(伴随)次数。a,φ,νa,\varphi,\nu 与伴随的求解每次约用 NN 次迭代,行源项的求解在较大网格上少一些。预处理(第 17 节)能减少每次求解的迭代次数,但前向路线仍要 nDn_D 次求解,伴随路线一次。
Figure 57 · The cost of the two routes (unlimited linear, default design; logarithmic vertical axis): the calls of residual_d (tangent) and residual_b (adjoint) made by unpreconditioned GMRES. The solves for a,φ,ν and the adjoint solve take about N iterations each, the solves for the row sources somewhat fewer on the larger meshes. Preconditioning () reduces the iterations of each solve, but the tangent route still needs n_D solves and the adjoint route one.110100103​104​23888N = 84730416N = 1695102832N = 32191328364N = 64calls of the tangent or reverse codetangent route, nD​ = 3tangent route, nD​ = N + 4adjoint route (either nD​)
Figure 57 · The cost of the two routes (unlimited linear, default design; logarithmic vertical axis): the calls of residual_d (tangent) and residual_b (adjoint) made by unpreconditioned GMRES. The solves for a,φ,νa,\varphi,\nu and the adjoint solve take about NN iterations each, the solves for the row sources somewhat fewer on the larger meshes. Preconditioning (Section 17) reduces the iterations of each solve, but the tangent route still needs nDn_D solves and the adjoint route one.

用 LU 分解直接求解时情况不同:AA 分解一次后(部分选主元:PA=LUPA=LU),nDn_D 个前向右端项与一个伴随右端项(AT=UTLTPA^T=U^TL^TP 用同一组因子)都只需三角求解(前代与回代),差别小得多。伴随的优势在矩阵不显式形成、每次求解都要迭代的大问题里才显著——这正是 CFD 的常态。若有 nJn_J 个目标,伴随路线要解 nJn_J 次,前向路线仍是 nDn_D 次:哪条路线便宜取决于 nDn_D 与 nJn_J 谁大。

With a direct LU solve the picture is different: once AA is factored (with partial pivoting, PA=LUPA=LU), the nDn_D tangent right-hand sides and the one adjoint right-hand side (AT=UTLTPA^T=U^TL^TP reuses the same factors) each cost only triangular solves, and the difference is small. The adjoint pays off in large problems where the matrix is never formed and every solve is an iteration, which is the normal case in CFD. With nJn_J objectives the adjoint route needs nJn_J solves and the tangent route still nDn_D: which route is cheaper depends on whether nDn_D or nJn_J is larger.

第 12 节Section 12

设计导数:设计从哪里进入残差

The design derivatives: where the design enters the residual

本节实验:先预测振幅的梯度 dJh/da=−0.1781\mathrm dJ_h/\mathrm da=−0.1781(N=8N=8)主要来自内部各行(源项)还是两个约束行;再想一想:连续问题的 dJ/dν=0\mathrm dJ/\mathrm d\nu=0 是精确的,N=8N=8 时 dJh/dν=0.0039\mathrm dJ_h/\mathrm d\nu=0.0039 很小——它小是因为格式在 ν\nu 上很准吗?对照 N=16N=16(图 65)。

Experiment: Predict first: where does the amplitude gradient dJh/da=−0.1781\mathrm dJ_h/\mathrm da=−0.1781 (N=8N=8) come from, the interior rows (the source) or the two constraint rows? And the continuous dJ/dν=0\mathrm dJ/\mathrm d\nu=0 exactly, while dJh/dν=0.0039\mathrm dJ_h/\mathrm d\nu=0.0039 at N=8N=8 is small: is it small because the scheme is accurate in ν\nu? Compare N=16N=16 (Figure 65).

第 10 节与第 11 节把 RDR_D 当作一个整体使用。本节把它打开:每个设计分量从哪里进入残差,每条进入路径对梯度贡献多少,这些部分怎样收敛到连续梯度的两项,以及剩下的误差来自哪里。

Section 10 and Section 11 used RDR_D as a whole. This section opens it: where each design component enters the residual, how much each path contributes to the gradient, how the pieces converge to the two terms of the continuous gradient, and where the remaining error comes from.

每个设计变量改变什么

What each design variable changes

构造解的公式(第 1 节)给出每个量对每个设计变量的精确导数。下表列出它们,最后一列是连续目标的精确梯度:

The formulas of the manufactured solution (Section 1) give the exact derivative of every quantity with respect to every design variable. The table lists them; the last column is the exact gradient of the continuous objective:

设计变量Design variable∂u∗/∂Dk\partial u^*/\partial D_k∂uin/∂Dk=∂uout/∂Dk\partial u_{\rm in}/\partial D_k=\partial u_{\rm out}/\partial D_k∂Qf/∂Dk\partial Q_f/\partial D_k(Qf=q∗(xf+1/2)Q_f=q^*(x_{f+1/2}))∂Qf/∂Dk\partial Q_f/\partial D_k, Qf=q∗(xf+1/2)Q_f=q^*(x_{f+1/2})进入残差的位置Where it enters the residual∂J∗/∂Dk\partial J^*/\partial D_k
aasin⁡ z\sin\,z−sin⁡ 2πφ-\sin\,2\pi\varphiu∗ sin⁡ z−2πν cos⁡ zu^*\,\sin\,z-2\pi\nu\,\cos\,z约束行 00、NN(边界值)与源项行constraint rows 00, NN (boundary values) and source rows−cos⁡ 2πφ/(2π)-\cos\,2\pi\varphi/(2\pi)
φ\varphi−2πa cos⁡ z-2\pi a\,\cos\,z−2πa cos⁡ 2πφ-2\pi a\,\cos\,2\pi\varphi−2πa u∗ cos⁡ z−4π2νa sin⁡ z-2\pi a\,u^*\,\cos\,z-4\pi^2\nu a\,\sin\,z同上likewisea sin⁡ 2πφa\,\sin\,2\pi\varphi
ν\nu0000−2πa cos⁡ z=−ux∗-2\pi a\,\cos\,z=-u^*_x源项行,以及每个面的通量:∂Hf/∂ν=−(Uf+1−Uf)/h\partial H_f/\partial\nu=-(U_{f+1}-U_f)/hsource rows, and the flux of every face: ∂Hf/∂ν=−(Uf+1−Uf)/h\partial H_f/\partial\nu=-(U_{f+1}-U_f)/h00

默认设计下精确梯度是 (−0.144008, 0.085156, 0.000000)(−0.144008,\ 0.085156,\ 0.000000)。ν\nu 的一行最特别:解与目标都不依赖 ν\nu,但源项的精确通量 QfQ_f 依赖(−νux∗-\nu u^*_x 是源项必须补上的扩散),离散通量也依赖。边界值 uin,uoutu_{\rm in},u_{\rm out} 在格点格式里只进入两个约束行。

At the default design the exact gradient is (−0.144008, 0.085156, 0.000000)(−0.144008,\ 0.085156,\ 0.000000). The ν\nu row is the special one: neither the solution nor the objective depends on ν\nu, but the exact flux QfQ_f of the source does (−νux∗-\nu u^*_x is the diffusion the source has to supply), and so does the discrete flux. On the node scheme the boundary values uin,uoutu_{\rm in},u_{\rm out} enter only the two constraint rows.

矩阵 RDR_D

The matrix RDR_D

RDR_D 是 (N+1)×3(N+1)\times3 矩阵,每列是第 10 节的一个右端项(差一个负号)。下表是 N=8N=8 的 RDR_D。aa 与 φ\varphi 两列不含状态:第 00、NN 行是 −∂uin/∂Dk-\partial u_{\rm in}/\partial D_k、−∂uout/∂Dk-\partial u_{\rm out}/\partial D_k,内部行只来自精确通量 QfQ_f,所以三种重构的这两列完全相同(最大差 00);ν\nu 列含 Uf+1−UfU_{f+1}-U_f,随重构而变,在第 00、NN 行恰为零。

RDR_D is an (N+1)×3(N+1)\times3 matrix; each column is one right-hand side of Section 10 (up to the sign). The table shows RDR_D for N=8N=8. The aa and φ\varphi columns contain no state: rows 00 and NN are −∂uin/∂Dk-\partial u_{\rm in}/\partial D_k and −∂uout/∂Dk-\partial u_{\rm out}/\partial D_k, the interior rows come only from the exact flux QfQ_f, so they are the same for the three reconstructions (largest difference 00). The ν\nu column contains Uf+1−UfU_{f+1}-U_f, changes with the reconstruction, and is exactly zero in rows 00 and NN.

RDR_D(N=8N=8,无限制器线性,默认设计)RDR_D (N=8N=8, unlimited linear, default design)
行 jjRow jj(RD)j0(R_D)_{j0}(aa)(RD)j0(R_D)_{j0} (aa)(RD)j1(R_D)_{j1}(φ\varphi)(RD)j1(R_D)_{j1} (φ\varphi)(RD)j2(R_D)_{j2}(ν\nu)(RD)j2(R_D)_{j2} (ν\nu)
00.4257791.1370390.000000
1−0.826554−0.1320040.111187
2−0.478357−0.957802−0.022857
30.304158−1.062330−0.081614
40.781016−0.350909−0.118902
50.6462630.405868−0.101704
60.2604230.7312420.054198
7−0.1238670.7884660.336097
80.4257791.1370390.000000

每一列的三个部分

The three pieces of a column

取 𝐔˙=0\dot{\mathbf U}=0、D˙=ek\dot D=e_k,第 8 节的前向面语句里 q˙L,q˙R,U˙L,U˙R\dot q_L,\dot q_R,\dot U_L,\dot U_R 全为零(设计不进入任何迹),只剩 H˙f=−ν˙ (Uf+1−Uf)/h\dot H_f=-\dot\nu\,(U_{f+1}-U_f)/h,它只在 k=2k=2 时不为零。按残差的分发方式进入各行,再加上源项语句与约束行,就是 RDekR_D e_k 的三个部分:

With 𝐔˙=0\dot{\mathbf U}=0 and D˙=ek\dot D=e_k, the tangent face statement of Section 8 has q˙L,q˙R,U˙L,U˙R\dot q_L,\dot q_R,\dot U_L,\dot U_R all zero (the design enters no trace) and only H˙f=−ν˙ (Uf+1−Uf)/h\dot H_f=-\dot\nu\,(U_{f+1}-U_f)/h remains, nonzero for k=2k=2 only. Scattered the way the residual is scattered, together with the source statement and the constraint rows it gives the three pieces of RDekR_De_k:

RDek=RDsrcek+RDfluxek+RDbcek,(RDsrc)jk=−(∂Qj∂Dk−∂Qj−1∂Dk),(RDflux)j2=∂Hj∂ν−∂Hj−1∂ν=−Uj+1−2Uj+Uj−1h(1≤j≤N−1),(RDbc)0k=−∂uin∂Dk,(RDbc)Nk=−∂uout∂Dk.\begin{aligned}R_De_k&=R_D^{\rm src}e_k+R_D^{\rm flux}e_k+R_D^{\rm bc}e_k,\\(R_D^{\rm src})_{jk}&=-\Bigl(\frac{\partial Q_j}{\partial D_k}-\frac{\partial Q_{j-1}}{\partial D_k}\Bigr),\qquad(R_D^{\rm flux})_{j2}=\frac{\partial H_j}{\partial\nu}-\frac{\partial H_{j-1}}{\partial\nu}=-\frac{U_{j+1}-2U_j+U_{j-1}}{h}\qquad(1\le j\le N-1),\\(R_D^{\rm bc})_{0k}&=-\frac{\partial u_{\rm in}}{\partial D_k},\qquad(R_D^{\rm bc})_{Nk}=-\frac{\partial u_{\rm out}}{\partial D_k}.\end{aligned}

第一、二部分在内部行(1≤j≤N−11\le j\le N-1),第三部分只在两个约束行。格心页还要把边界部分再分成对流与黏性两块(它们来自边界面上的 cL(0)c_L(0) 与 2ν/h2\nu/h);这里没有边界面的特殊处理,边界部分就是约束行本身。本页从前向代码自己的中间量读出这三部分;三部分之和与前向代码算出的 RDR_D 完全相同;check_d.js 还用独立的复数步长实现逐项核对了每一部分。图 58 把它们画成堆叠柱。

The first two pieces sit in the interior rows (1≤j≤N−11\le j\le N-1), the third in the two constraint rows only. The cell-centred page has to split its boundary part into a convective and a viscous block (they come from cL(0)c_L(0) and 2ν/h2\nu/h of the boundary face); here there is no special boundary face, and the boundary part is the constraint rows themselves. The page reads the three pieces off the intermediate values of the tangent code; their sum equals the RDR_D of the tangent code exactly, and check_d.js holds each piece separately to an independent complex-step implementation. Figure 58 draws them as stacked bars.

图 58 · R_D 每一列的三个部分(N=8,无限制器线性,默认设计):源项行(橙黄)、约束行(紫,只有 a、φ 两列)、通量中的 ν(蓝,只有 ν 列);圆点是它们的和,即 R_De_k。ν 列的两部分只在面上导数的误差从一个面到下一个面变化很小(|E_j-E_(j-1)| 比精确面导数在这两个面之间的变化小得多)的行里几乎抵消,并不是在面上导数准确的行里(第 2、3、6 行分别抵消到较大一部分的 2.6%、9.0%、6.2%;第 1、4、5、7 行只部分抵消);两个约束行在 ν 列里恰为零。源项行约束行(边界值)通量中的 ν和−0.500.500.51xk = 0:振幅 a,RD​ e0​−1−0.500.5100.51xk = 1:相位 φ,RD​ e1​−1−0.500.5100.51xk = 2:黏性 ν,RD​ e2​
图 58 · RDR_D 每一列的三个部分(N=8N=8,无限制器线性,默认设计):源项行(橙黄)、约束行(紫,只有 aa、φ\varphi 两列)、通量中的 ν\nu(蓝,只有 ν\nu 列);圆点是它们的和,即 RDekR_De_k。ν\nu 列的两部分只在面上导数的误差从一个面到下一个面变化很小(∣Ej−Ej−1∣|E_j-E_{j-1}| 比精确面导数在这两个面之间的变化小得多)的行里几乎抵消,并不是在面上导数准确的行里(第 2、3、6 行分别抵消到较大一部分的 2.6%、9.0%、6.2%;第 1、4、5、7 行只部分抵消);两个约束行在 ν\nu 列里恰为零。
Figure 58 · The three pieces of each column of R_D (N=8, unlimited linear, default design): source rows (amber), constraint rows (violet; the a and φ columns only), and the ν of the flux (blue; the ν column only); the dots are their sum, R_De_k. In the ν column the two interior pieces nearly cancel only in rows where the error of the face gradient changes little from one face to the next (|E_j-E_(j-1)| is small against the change of the exact face gradient between the two faces), not where the face gradients are accurate (rows 2, 3, 6 cancel to 2.6%, 9.0%, 6.2% of the larger piece; rows 1, 4, 5, 7 only partly); the two constraint rows are exactly zero in the ν column.source rowsconstraint rows (boundary values)ν in the fluxsum−0.500.500.51xk = 0: amplitude a: RD​ e0​−1−0.500.5100.51xk = 1: phase φ: RD​ e1​−1−0.500.5100.51xk = 2: viscosity ν: RD​ e2​
Figure 58 · The three pieces of each column of RDR_D (N=8N=8, unlimited linear, default design): source rows (amber), constraint rows (violet; the aa and φ\varphi columns only), and the ν\nu of the flux (blue; the ν\nu column only); the dots are their sum, RDekR_De_k. In the ν\nu column the two interior pieces nearly cancel only in rows where the error of the face gradient changes little from one face to the next (∣Ej−Ej−1∣|E_j-E_{j-1}| is small against the change of the exact face gradient between the two faces), not where the face gradients are accurate (rows 2, 3, 6 cancel to 2.6%, 9.0%, 6.2% of the larger piece; rows 1, 4, 5, 7 only partly); the two constraint rows are exactly zero in the ν\nu column.

梯度从哪里来

Where the gradient comes from

把伴随与每一部分做内积,梯度 dJh/dDk\mathrm dJ_h/\mathrm dD_k 就被分成同样的三部分 ψTRDsrcek\psi^TR_D^{\rm src}e_k、ψTRDfluxek\psi^TR_D^{\rm flux}e_k、ψTRDbcek\psi^TR_D^{\rm bc}e_k。第三部分有一个简单的形式:约束行只含 ψ0\psi_0 与 ψN\psi_N,

Dotting the adjoint with every piece splits the gradient dJh/dDk\mathrm dJ_h/\mathrm dD_k into the same three parts, ψTRDsrcek\psi^TR_D^{\rm src}e_k, ψTRDfluxek\psi^TR_D^{\rm flux}e_k and ψTRDbcek\psi^TR_D^{\rm bc}e_k. The third has a simple form: the constraint rows involve only ψ0\psi_0 and ψN\psi_N,

ψTRDbcek=−ψ0 ∂uin∂Dk−ψN ∂uout∂Dk,uˉin=−ψ0,uˉout=−ψN.\psi^TR_D^{\rm bc}e_k=-\psi_0\,\frac{\partial u_{\rm in}}{\partial D_k}-\psi_N\,\frac{\partial u_{\rm out}}{\partial D_k},\qquad \bar u_{\rm in}=-\psi_0,\qquad\bar u_{\rm out}=-\psi_N.

uˉin=−ψ0\bar u_{\rm in}=-\psi_0 是 JhJ_h 对入口值的导数(源项与出口值不变),uˉout=−ψN\bar u_{\rm out}=-\psi_N 同理(第 11 节)。默认设计下反向代码给出 uˉin=1.4061\bar u_{\rm in}=1.4061、uˉout=0.0870\bar u_{\rm out}=0.0870,对三种重构中的每一种都与 −ψ0-\psi_0、−ψN-\psi_N 完全相同;边界部分与上式相差不到 10−1510^{-15}。下表与图 59 给出梯度的三部分。

uˉin=−ψ0\bar u_{\rm in}=-\psi_0 is the derivative of JhJ_h with respect to the inlet value (with the source and the outlet value fixed), and uˉout=−ψN\bar u_{\rm out}=-\psi_N likewise (Section 11). At the default design the reverse code gives uˉin=1.4061\bar u_{\rm in}=1.4061 and uˉout=0.0870\bar u_{\rm out}=0.0870, which equal −ψ0-\psi_0 and −ψN-\psi_N exactly for each of the three reconstructions; the boundary part agrees with the formula above to within 10−1510^{-15}. The table and Figure 59 give the three parts of the gradient.

梯度的三部分(N=8N=8,默认设计)The three parts of the gradient (N=8N=8, default design)
重构Reconstruction分量ComponentψTRDsrcek\psi^TR_D^{\rm src}e_kψTRDfluxek\psi^TR_D^{\rm flux}e_kψTRDbcek\psi^TR_D^{\rm bc}e_k梯度Gradient
一阶first orderaa−0.446760.00000−0.72841−1.175176
一阶first orderφ\varphi1.710630.00000−1.94522−0.234594
一阶first orderν\nu1.62313−0.630550.000000.992575
无限制器线性unlimited linearaa0.457660.00000−0.63573−0.178061
无限制器线性unlimited linearφ\varphi2.117600.00000−1.697700.419904
无限制器线性unlimited linearν\nu2.18011−2.176200.000000.003909
光滑限制器smooth limiteraa0.462280.00000−0.65049−0.188210
光滑限制器smooth limiterφ\varphi2.290610.00000−1.737140.553468
光滑限制器smooth limiterν\nu2.33156−2.646560.00000−0.315000

实验的第一问有了答案:N=8N=8、无限制器线性时,aa 的梯度 −0.1781−0.1781 主要来自边界部分 −0.6357−0.6357(绝对值比梯度本身还大),符号相反的源项部分 0.45770.4577 抵消了其中约 72%;φ\varphi 更极端:2.11762.1176 与 −1.6977−1.6977 相加只剩 0.41990.4199。与格心页不同,这两部分在每个网格上都分别由内部各行与首末两行承载,不会在端单元里互相抵消。第二问:ν\nu 的两部分 2.18012.1801 与 −2.1762−2.1762 各自都是 O(1)O(1),N=8N=8 时几乎抵消,剩下 0.00390.0039;这种抵消是偶然的——N=16N=16 时剩 −0.0698−0.0698(后文)。

The first question of the experiment has its answer: at N=8N=8 with unlimited linear reconstruction, the aa-gradient −0.1781−0.1781 comes mainly from the boundary part −0.6357−0.6357, which is larger in magnitude than the gradient itself; the source part 0.45770.4577 has the opposite sign and cancels about 72% of it. φ\varphi is more extreme: 2.11762.1176 and −1.6977−1.6977 add up to only 0.41990.4199. Unlike on the cell page, the two parts are carried on every mesh by the interior rows and by the first and last row respectively, and do not cancel inside an end cell. The second question: the two parts of ν\nu, 2.18012.1801 and −2.1762−2.1762, are each of order one and nearly cancel at N=8N=8, leaving 0.00390.0039; that cancellation is accidental: N=16N=16 leaves −0.0698−0.0698 (below).

图 59 · 梯度的三部分:N=8、N=512(无限制器线性,默认设计)与连续梯度的两项。颜色同,圆点是总和。a、φ:边界部分(紫)在每个网格上都是 -(ψ_0+ψ_N) ∂ u_in/∂ D_k,N=8 时与连续边界项只差 3.1%;ν 的两部分(橙黄与蓝)各约 ∓ 1.88,只在连续问题里精确抵消。源项行约束行(边界值)通量中的 ν和−0.6−0.4−0.200.20.4k = 0:振幅 aN = 8N = 512连续−2−1012k = 1:相位 φN = 8N = 512连续−2−1012k = 2:黏性 νN = 8N = 512连续
图 59 · 梯度的三部分:N=8N=8、N=512N=512(无限制器线性,默认设计)与连续梯度的两项。颜色同图 58,圆点是总和。aa、φ\varphi:边界部分(紫)在每个网格上都是 −(ψ0+ψN) ∂uin/∂Dk-(\psi_0+\psi_N)\,\partial u_{\rm in}/\partial D_k,N=8N=8 时与连续边界项只差 3.1%;ν\nu 的两部分(橙黄与蓝)各约 ∓1.88\mp1.88,只在连续问题里精确抵消。
Figure 59 · The three parts of the gradient at N=8 and N=512 (unlimited linear, default design) and the two terms of the continuous gradient. Colours as in ; the dots are the totals. a, φ: the boundary part (violet) is -(ψ_0+ψ_N) ∂ u_in/∂ D_k on every mesh, and at N=8 it differs from the continuous boundary term by only 3.1%; the two parts of ν (amber and blue) are about ∓ 1.88 each and cancel exactly only in the continuous problem.source rowsconstraint rows (boundary values)ν in the fluxsum−0.6−0.4−0.200.20.4k = 0: amplitude aN = 8N = 512continuous−2−1012k = 1: phase φN = 8N = 512continuous−2−1012k = 2: viscosity νN = 8N = 512continuous
Figure 59 · The three parts of the gradient at N=8N=8 and N=512N=512 (unlimited linear, default design) and the two terms of the continuous gradient. Colours as in Figure 58; the dots are the totals. aa, φ\varphi: the boundary part (violet) is −(ψ0+ψN) ∂uin/∂Dk-(\psi_0+\psi_N)\,\partial u_{\rm in}/\partial D_k on every mesh, and at N=8N=8 it differs from the continuous boundary term by only 3.1%; the two parts of ν\nu (amber and blue) are about ∓1.88\mp1.88 each and cancel exactly only in the continuous problem.

连续梯度:两个相互抵消的大项

The continuous gradient: two large terms that cancel

对连续问题做同样的分解。附录 A 由连续伴随 λ\lambda(−uλx−νλxx=−(1+x)-u\lambda_x-\nu\lambda_{xx}=-(1+x),λ(0)=λ(1)=0\lambda(0)=\lambda(1)=0)推出梯度公式;它也有一个源项部分和一个边界部分,后者只有黏性:

The continuous problem splits the same way. Appendix A derives the gradient formula from the continuous adjoint λ\lambda (−uλx−νλxx=−(1+x)-u\lambda_x-\nu\lambda_{xx}=-(1+x), λ(0)=λ(1)=0\lambda(0)=\lambda(1)=0); it too has a source part and a boundary part, and the latter is purely viscous:

dJdDk=−∫01λ sDk dx+ν λx(1) ∂uout∂Dk−ν λx(0) ∂uin∂Dk(Dk=a,φ),dJdν=−∫01λ (sν+uxx∗) dx=0.\frac{\mathrm dJ}{\mathrm dD_k}=-\int_0^1\lambda\,s_{D_k}\,\mathrm dx+\nu\,\lambda_x(1)\,\frac{\partial u_{\rm out}}{\partial D_k}-\nu\,\lambda_x(0)\,\frac{\partial u_{\rm in}}{\partial D_k}\quad(D_k=a,\varphi),\qquad \frac{\mathrm dJ}{\mathrm d\nu}=-\int_0^1\lambda\,\bigl(s_\nu+u^*_{xx}\bigr)\,\mathrm dx=0.

它与离散梯度逐项对应(第 11 节的新结果):−ψ0↔−νλx(0)-\psi_0\leftrightarrow-\nu\lambda_x(0)、−ψN↔νλx(1)-\psi_N\leftrightarrow\nu\lambda_x(1),源项积分 ↔∑j=1N−1ψj(RD)jk\leftrightarrow\sum_{j=1}^{N-1}\psi_j(R_D)_{jk}。用独立求出的 λ\lambda(Chebyshev 配点,M=200M=200)计算两项:aa 的源项积分 0.47280.4728 与边界项 −0.6168−0.6168,φ\varphi 的 1.73231.7323 与 −1.6471−1.6471——各自都是 O(1)O(1),相加才得到小的精确梯度 (−0.144008, 0.085156)(−0.144008,\ 0.085156)(与闭式相差不到 10−1210^{-12})。边界项几乎全来自 x=0x=0:−νλx(0) ∂uin/∂Dk-\nu\lambda_x(0)\,\partial u_{\rm in}/\partial D_k 对 aa、φ\varphi 分别是 −0.6074−0.6074 与 −1.6221−1.6221,x=1x=1 只贡献 −0.0094−0.0094 与 −0.0251−0.0251。ν\nu 的两部分 −∫λsν=1.8769-\int\lambda s_\nu=1.8769 与 −∫λuxx∗=−1.8769-\int\lambda u^*_{xx}=−1.8769 逐点抵消:sν=4π2a sin⁡ z=−uxx∗s_\nu=4\pi^2a\,\sin\,z=-u^*_{xx},源项补上的扩散恰好是通量里 ν\nu 的作用。

It corresponds term by term to the discrete gradient (the new result of Section 11): −ψ0↔−νλx(0)-\psi_0\leftrightarrow-\nu\lambda_x(0), −ψN↔νλx(1)-\psi_N\leftrightarrow\nu\lambda_x(1), and the source integral ↔∑j=1N−1ψj(RD)jk\leftrightarrow\sum_{j=1}^{N-1}\psi_j(R_D)_{jk}. With an independently computed λ\lambda (Chebyshev collocation, M=200M=200) the two terms are: for aa the source integral 0.47280.4728 and the boundary term −0.6168−0.6168, for φ\varphi 1.73231.7323 and −1.6471−1.6471: each of order one, and only their sum is the small exact gradient (−0.144008, 0.085156)(−0.144008,\ 0.085156) (within 10−1210^{-12} of the closed form). The boundary term comes almost entirely from x=0x=0: −νλx(0) ∂uin/∂Dk-\nu\lambda_x(0)\,\partial u_{\rm in}/\partial D_k is −0.6074−0.6074 for aa and −1.6221−1.6221 for φ\varphi, while x=1x=1 adds only −0.0094−0.0094 and −0.0251−0.0251. The two parts of ν\nu, −∫λsν=1.8769-\int\lambda s_\nu=1.8769 and −∫λuxx∗=−1.8769-\int\lambda u^*_{xx}=−1.8769, cancel at every point: sν=4π2a sin⁡ z=−uxx∗s_\nu=4\pi^2a\,\sin\,z=-u^*_{xx}, the diffusion that the source supplies is exactly what ν\nu does in the flux.

离散的两部分怎样收敛

How the discrete parts converge

离散梯度的边界部分是 −(ψ0+ψN) ∂uin/∂Dk-(\psi_0+\psi_N)\,\partial u_{\rm in}/\partial D_k,它随乘子收敛到连续边界项(第 11 节:ψ0→νλx(0)\psi_0\to\nu\lambda_x(0),ψN→−νλx(1)\psi_N\to-\nu\lambda_x(1));源项部分是 −∑j=1N−1ψj∫VjsDk dx-\sum_{j=1}^{N-1}\psi_j\int_{V_j}s_{D_k}\,\mathrm dx,在 ψj→λ(xj)\psi_j\to\lambda(x_j) 时收敛到 −∫λsDk dx-\int\lambda s_{D_k}\,\mathrm dx。图 60 用带状求解器从 N=8N=8 测到 40964096:两部分分别趋向连续的两项。

The boundary part of the discrete gradient is −(ψ0+ψN) ∂uin/∂Dk-(\psi_0+\psi_N)\,\partial u_{\rm in}/\partial D_k, which follows the multipliers to the continuous boundary term (Section 11: ψ0→νλx(0)\psi_0\to\nu\lambda_x(0), ψN→−νλx(1)\psi_N\to-\nu\lambda_x(1)); the source part is −∑j=1N−1ψj∫VjsDk dx-\sum_{j=1}^{N-1}\psi_j\int_{V_j}s_{D_k}\,\mathrm dx, which tends to −∫λsDk dx-\int\lambda s_{D_k}\,\mathrm dx as ψj→λ(xj)\psi_j\to\lambda(x_j). Figure 60 measures it with the banded solver from N=8N=8 to 40964096: each part approaches its continuous term.

图 60 · 离散梯度的两部分随网格加密的变化(无限制器线性,默认设计;带状求解器)。橙黄:源项部分;紫:边界部分;深色:梯度;虚线是连续的源项积分、边界项与精确梯度。N=4096 时两部分与连续值分别相差 7.1 × 10^(-8) 与 1.3 × 10^(-8)(a)。源项部分 ψT​ RD​src​ ek​边界部分 −(ψ0​+ψN​) ∂uin​/∂Dk​梯度虚线:连续值−0.6−0.4−0.200.20.48645124096Nk = 0:振幅 a−2−10128645124096Nk = 1:相位 φ
图 60 · 离散梯度的两部分随网格加密的变化(无限制器线性,默认设计;带状求解器)。橙黄:源项部分;紫:边界部分;深色:梯度;虚线是连续的源项积分、边界项与精确梯度。N=4096N=4096 时两部分与连续值分别相差 7.1×10−87.1\times10^{-8} 与 1.3×10−81.3\times10^{-8}(aa)。
Figure 60 · The two parts of the discrete gradient under refinement (unlimited linear, default design; banded solver). Amber: source part; violet: boundary part; dark: the gradient; dashed: the continuous source integral, boundary term and exact gradient. At N=4096 the two parts are within 7.1 × 10^(-8) and 1.3 × 10^(-8) of their continuous values (a).source part ψT​ RD​src​ ek​boundary part −(ψ0​+ψN​) ∂uin​/∂Dk​gradientdashed: continuous−0.6−0.4−0.200.20.48645124096Nk = 0: amplitude a−2−10128645124096Nk = 1: phase φ
Figure 60 · The two parts of the discrete gradient under refinement (unlimited linear, default design; banded solver). Amber: source part; violet: boundary part; dark: the gradient; dashed: the continuous source integral, boundary term and exact gradient. At N=4096N=4096 the two parts are within 7.1×10−87.1\times10^{-8} and 1.3×10−81.3\times10^{-8} of their continuous values (aa).
离散梯度两部分的收敛(无限制器线性,默认设计;带状求解器);最后一行是连续值与边界通量Convergence of the two parts of the discrete gradient (unlimited linear, default design; banded solver); the last row gives the continuous values and the boundary fluxes
NψTRDsrce0\psi^TR_D^{\rm src}e_0−(ψ0+ψN) ∂auin-(\psi_0+\psi_N)\,\partial_a u_{\rm in}ψTRDsrce1\psi^TR_D^{\rm src}e_1−(ψ0+ψN) ∂φuin-(\psi_0+\psi_N)\,\partial_\varphi u_{\rm in}ψ0\psi_0ψN\psi_N
80.4577−0.63572.1176−1.6977−1.4061−0.0870
320.4782−0.61691.7486−1.6473−1.4136−0.0352
1280.4730−0.61681.7325−1.6471−1.4247−0.0239
5120.4728−0.61681.7323−1.6471−1.4264−0.0222
20480.4728−0.61681.7323−1.6471−1.4266−0.0220
40960.4728−0.61681.7323−1.6471−1.4266−0.0220
连续continuous0.4728−0.61681.7323−1.6471−1.4266−0.0220

边界部分与连续边界项的相对差在 N=8N=8 时是 3.1%,N=64N=64 时是 1.4e−5,N=512N=512 时是 9.4e−7(aa 与 φ\varphi 相同);aa 的源项部分与连续源项积分的相对差在 N=8N=8 时是 3.2%,N=64N=64 时是 2.5e−3,N=512N=512 时是 4.1e−7;φ\varphi 的在 N=8N=8 时差 22%,N=64N=64 时是 1.5e−3,N=512N=512 时是 1.1e−5。N=8N=8 时边界部分与 aa 的源项部分都在几个百分点以内,尽管入口层没有被分辨;φ\varphi 的源项部分不是(22%,绝对误差 0.385,是精确梯度 0.0852 的 4.5 倍)。梯度是两个 O(1)O(1) 项的小差,所以一项的几个百分点已经是梯度的很大一部分。

Relative to the continuous boundary term, the boundary part is off by 3.1% at N=8N=8, by 1.4e−5 at N=64N=64 and by 9.4e−7 at N=512N=512 (the same for aa and φ\varphi); relative to the continuous source integral, the source part of aa is off by 3.2% at N=8N=8, by 2.5e−3 at N=64N=64 and by 4.1e−7 at N=512N=512; that of φ\varphi by 22% at N=8N=8, 1.5e−3 at N=64N=64 and 1.1e−5 at N=512N=512. At N=8N=8 the boundary part and the source part of aa are within a few percent although the inlet layer is not resolved; the source part of φ\varphi is not (22%, absolute error 0.385, 4.5 times the exact gradient 0.0852). The gradient is the small difference of two terms of order one, so a few percent of one term is a large share of it.

误差来自哪里

Where the error comes from

离散梯度 dJh/dD\mathrm dJ_h/\mathrm dD 是离散目标的精确导数:前向、伴随、复数步长与差分在本页检验过的每个网格上都一致(第 13、14 节)。它与连续梯度的差是离散化误差,不是求导错误。格心页把粗网格上的大误差主要归因于两个未做重构的端单元;格点格式没有端单元,两个边界节点用单侧斜率做了二阶重构,那种解释在这里不适用。下面逐项测量,结论只限于所测范围,并写明局限。

The discrete gradient dJh/dD\mathrm dJ_h/\mathrm dD is the exact derivative of the discrete objective: tangent, adjoint, complex step and differences agree on every mesh tested on this page (Sections 13 and 14). Its difference from the continuous gradient is a discretisation error, not a differentiation error. The cell-centred page attributes the large coarse-mesh error mainly to its two unreconstructed end cells; the node scheme has no end cells, and its two boundary nodes are reconstructed at second order with a one-sided slope, so that explanation does not carry over. What follows measures it item by item; the conclusions hold for the ranges measured, and the limits are stated.

预算:源项部分、边界部分

The budget: source part and boundary part

把梯度的误差 dJh/dDk−dJ/dDk\mathrm dJ_h/\mathrm dD_k-\mathrm dJ/\mathrm dD_k 拆成两部分各自的误差(源项部分减源项积分,边界部分减边界项;ν\nu 则是源项部分与通量部分)。N=8N=8 时 aa 的两个误差同号、大小相近(源项 −0.0151−0.0151,边界 −0.0189−0.0189),边界部分的误差又主要来自出口乘子(出口 −0.0277−0.0277,入口 0.00870.0087):这是第 11 节里 ψN\psi_N 在粗网格上相对误差大的后果。φ\varphi 的误差在 N=8N=8 时几乎全来自源项部分(源项 0.3850.385,边界 −0.051−0.051)。网格加密后,aa 的源项部分的误差在 N=16N=16 到 256256、N≥1024N\ge1024 时比边界部分大(N=16,32,64N=16,32,64 时大 9、71、141 倍),φ\varphi 的源项误差在每个网格上都更大;ν\nu 的通量部分的误差在 N=16N=16 到 512512、N≥2048N\ge2048 时更大。图 61 画出全部。

Split the error of the gradient, dJh/dDk−dJ/dDk\mathrm dJ_h/\mathrm dD_k-\mathrm dJ/\mathrm dD_k, into the errors of its two parts (the source part minus the source integral, the boundary part minus the boundary term; for ν\nu the source part and the flux part). At N=8N=8 the two errors of aa have the same sign and similar size (source −0.0151−0.0151, boundary −0.0189−0.0189), and the error of the boundary part comes mainly from the outlet multiplier (outlet −0.0277−0.0277, inlet 0.00870.0087): the consequence of the large relative error of ψN\psi_N on coarse meshes (Section 11). The error of φ\varphi at N=8N=8 comes almost entirely from the source part (source 0.3850.385, boundary −0.051−0.051). Under refinement the error of the source part of aa is the larger one for N=16N=16 to 256256, N≥1024N\ge1024 (9, 71 and 141 times the boundary part's at N=16,32,64N=16,32,64), the source error of φ\varphi is the larger on every mesh, and the error of the flux part of ν\nu is the larger for N=16N=16 to 512512, N≥2048N\ge2048. Figure 61 shows all of it.

图 61 · 梯度误差的分解(无限制器线性,默认设计,双对数图,画的是绝对值):源项部分的误差(橙黄)、边界部分(紫,a,φ)或通量部分(蓝,ν)的误差,以及梯度本身的误差(圈)。曲线上的凹口是误差变号的地方;梯度误差变号的网格(格点格式,无限制器线性):a 在 N=16, 1024,φ 在 N=256,ν 在 N=16, 2048。源项部分边界部分(a、φ)通量部分(ν)梯度10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​8645124096Nk = 0:振幅 a10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​18645124096Nk = 1:相位 φ10-7​10-6​10-5​10-4​10-3​10-2​10-1​18645124096Nk = 2:黏性 ν
图 61 · 梯度误差的分解(无限制器线性,默认设计,双对数图,画的是绝对值):源项部分的误差(橙黄)、边界部分(紫,a,φa,\varphi)或通量部分(蓝,ν\nu)的误差,以及梯度本身的误差(圈)。曲线上的凹口是误差变号的地方;梯度误差变号的网格(格点格式,无限制器线性):aa 在 N=16,1024N=16, 1024,φ\varphi 在 N=256N=256,ν\nu 在 N=16,2048N=16, 2048。
Figure 61 · The error budget of the gradient (unlimited linear, default design, log axes, absolute values): the error of the source part (amber), of the boundary part (violet, a,φ) or of the flux part (blue, ν), and the error of the gradient itself (rings). The notches are where an error changes sign; the gradient error changes sign (node scheme, unlimited linear) at N=16, 1024 for a, N=256 for φ and N=16, 2048 for ν.source partboundary part (a, φ)flux part (ν)gradient10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​8645124096Nk = 0: amplitude a10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​18645124096Nk = 1: phase φ10-7​10-6​10-5​10-4​10-3​10-2​10-1​18645124096Nk = 2: viscosity ν
Figure 61 · The error budget of the gradient (unlimited linear, default design, log axes, absolute values): the error of the source part (amber), of the boundary part (violet, a,φa,\varphi) or of the flux part (blue, ν\nu), and the error of the gradient itself (rings). The notches are where an error changes sign; the gradient error changes sign (node scheme, unlimited linear) at N=16,1024N=16, 1024 for aa, N=256N=256 for φ\varphi and N=16,2048N=16, 2048 for ν\nu.

哪些控制体贡献误差

Which volumes contribute

源项部分是对内部节点的和,所以它的误差可以逐个对偶控制体地读出:ej=ψj(RDsrc)jk−(−∫Vjλ sDk dx)e_j=\psi_j(R_D^{\rm src})_{jk}-\bigl(-\int_{V_j}\lambda\,s_{D_k}\,\mathrm dx\bigr)。连续积分是在整个 [0,1][0,1] 上,而节点 00 与 NN 的半个控制体没有行(它们是约束行),这两块 ∫0h/2λsDk\int_0^{h/2}\lambda s_{D_k}、∫1−h/21λsDk\int_{1-h/2}^1\lambda s_{D_k} 要另外算进去,否则逐控制体的误差加不起来。图 62 把全部画出:橙黄柱是 eje_j,紫柱是两端的半个控制体(符号取负,即它们在误差里的份额),黑线是从入口起的累加和,终点就是源项部分的误差。

The source part is a sum over the interior nodes, so its error can be read off dual volume by dual volume: ej=ψj(RDsrc)jk−(−∫Vjλ sDk dx)e_j=\psi_j(R_D^{\rm src})_{jk}-\bigl(-\int_{V_j}\lambda\,s_{D_k}\,\mathrm dx\bigr). The continuous integral runs over the whole of [0,1][0,1], whereas the two half volumes of nodes 00 and NN have no row (they are constraint rows); the two pieces ∫0h/2λsDk\int_0^{h/2}\lambda s_{D_k} and ∫1−h/21λsDk\int_{1-h/2}^1\lambda s_{D_k} must be counted separately, or the per-volume errors do not add up. Figure 62 draws everything: the amber bars are eje_j, the violet bars the two half volumes (sign reversed, i.e. their share of the error), the black line the running sum from the inlet, whose end point is the error of the source part.

图 62 · 源项部分的逐控制体误差(无限制器线性,默认设计;上排 a,下排 φ;各图纵轴不同):橙黄柱:内部控制体的误差 e_j;紫柱:入口与出口的半个控制体(没有行);黑线:从入口起的累加和,其终点(标题里的“净”)就是源项部分的误差。N=8 时 a 的最大单项是净值的 28 倍,符号有正有负;N=64 时误差分布在整个区间上,入口附近的几个控制体项较大,但被入口半个控制体抵消了大半。内部控制体的误差 ej​两端的半个控制体(没有行)累加和,终点 = 净误差−0.4−0.200.200.51xN = 8,净 −1.5e−2−0.15−0.1−0.0500.050.100.51xN = 16,净 1.6e−2−0.06−0.04−0.0200.0200.51xN = 32,净 5.4e−3−0.015−0.01−0.00500.00500.51xN = 64,净 1.2e−3−0.100.10.20.30.400.51xN = 8,净 3.9e−1−0.0500.050.10.1500.51xN = 16,净 8.4e−2−0.0200.020.0400.51xN = 32,净 1.6e−2−0.01−0.00500.0050.010.01500.51xN = 64,净 2.6e−3
图 62 · 源项部分的逐控制体误差(无限制器线性,默认设计;上排 aa,下排 φ\varphi;各图纵轴不同):橙黄柱:内部控制体的误差 eje_j;紫柱:入口与出口的半个控制体(没有行);黑线:从入口起的累加和,其终点(标题里的“净”)就是源项部分的误差。N=8N=8 时 aa 的最大单项是净值的 28 倍,符号有正有负;N=64N=64 时误差分布在整个区间上,入口附近的几个控制体项较大,但被入口半个控制体抵消了大半。
Figure 62 · The per-volume errors of the source part (unlimited linear, default design; top row a, bottom row φ; every panel has its own vertical axis): amber bars: the errors e_j of the interior volumes; violet bars: the two half volumes at the inlet and the outlet (no row); black line: the running sum from the inlet, whose end point (the “net” in the title) is the error of the source part. At N=8 the largest single term for a is 28 times the net, and the terms have both signs; at N=64 the error is spread over the whole interval, with a few larger terms next to the inlet that the inlet half volume largely cancels.error ej​ of an interior volumethe two half volumes (no row)running sum, end = net error−0.4−0.200.200.51xN = 8, net −1.5e−2−0.15−0.1−0.0500.050.100.51xN = 16, net 1.6e−2−0.06−0.04−0.0200.0200.51xN = 32, net 5.4e−3−0.015−0.01−0.00500.00500.51xN = 64, net 1.2e−3−0.100.10.20.30.400.51xN = 8, net 3.9e−1−0.0500.050.10.1500.51xN = 16, net 8.4e−2−0.0200.020.0400.51xN = 32, net 1.6e−2−0.01−0.00500.0050.010.01500.51xN = 64, net 2.6e−3
Figure 62 · The per-volume errors of the source part (unlimited linear, default design; top row aa, bottom row φ\varphi; every panel has its own vertical axis): amber bars: the errors eje_j of the interior volumes; violet bars: the two half volumes at the inlet and the outlet (no row); black line: the running sum from the inlet, whose end point (the “net” in the title) is the error of the source part. At N=8N=8 the largest single term for aa is 28 times the net, and the terms have both signs; at N=64N=64 the error is spread over the whole interval, with a few larger terms next to the inlet that the inlet half volume largely cancels.

N=8N=8 时 aa 的各项为 0.243、0.025、0.019、0.063、0.052、0.026、0.003(内部控制体)、−0.431−0.431(入口半个控制体)与 −0.014−0.014(出口半个控制体),大小从 0.0030.003 到 0.430.43。内部项与入口半个控制体互相抵消到 −0.0007−0.0007,所以净值 −0.0151−0.0151 的 95% 是出口半个控制体;φ\varphi 的入口半个控制体(0.2800.280)占净值 0.3850.385 的 73%。到 N=64N=64,xj≤0.1x_j\le0.1 的控制体项加起来是 0.01390.0139,入口半个控制体拿走 0.01630.0163,两者净 −0.0024−0.0024;其余控制体(含出口半个控制体)贡献 0.00360.0036:总的源项误差 0.00120.0012 是两块符号相反、大小相近的贡献之和(φ\varphi:0.00480.0048 与 −0.0022−0.0022)。入口附近的控制体项最大,这与入口层有关,但数据既不支持也不排除把误差归因于层:ν≤0.02\nu\le0.02 时误差几乎不随 ν\nu 变,未被分辨的层同样如此(见下文)。

At N=8N=8 the terms for aa are 0.243, 0.025, 0.019, 0.063, 0.052, 0.026, 0.003 (interior volumes), −0.431−0.431 (inlet half volume) and −0.014−0.014 (outlet half volume); they range in size from 0.0030.003 to 0.430.43. The interior terms and the inlet half volume cancel to −0.0007−0.0007, so the net −0.0151−0.0151 is 95% the outlet half volume; for φ\varphi the inlet half volume (0.2800.280) is 73% of the net 0.3850.385. At N=64N=64 the volumes with xj≤0.1x_j\le0.1 add up to 0.01390.0139 and the inlet half volume takes away 0.01630.0163, a net of −0.0024−0.0024; the other volumes (the outlet half volume included) contribute 0.00360.0036: the total source error 0.00120.0012 is the sum of two contributions of opposite signs and similar size (φ\varphi: 0.00480.0048 and −0.0022−0.0022). The volume terms next to the inlet are the largest, which has to do with the inlet layer, but the data neither support nor exclude blaming the layer: for ν≤0.02\nu\le0.02 the errors hardly vary with ν\nu, which an unresolved layer would also produce (below).

梯度误差是切线误差的加权和

The gradient error is the weighted error of the tangent

同一个误差还有另一种读法,它把本节和第 10 节连起来。对 aa、φ\varphi,J˙k=wTvk\dot J_k=w^Tv_k 而连续值是 ∫01(1+x) uDk∗ dx\int_0^1(1+x)\,u^*_{D_k}\,\mathrm dx,所以

The same error has a second reading, which ties this section to Section 10. For aa and φ\varphi, J˙k=wTvk\dot J_k=w^Tv_k while the continuous value is ∫01(1+x) uDk∗ dx\int_0^1(1+x)\,u^*_{D_k}\,\mathrm dx, so

dJhdDk−dJdDk=wT(vk−uDk∗(𝐱))⏟(1)+wTuDk∗(𝐱)−∫01(1+x) uDk∗ dx⏟(2)(k=0,1),dJhdν=wTv2.\frac{\mathrm dJ_h}{\mathrm dD_k}-\frac{\mathrm dJ}{\mathrm dD_k}=\underbrace{w^T\bigl(v_k-u^*_{D_k}(\mathbf x)\bigr)}_{(1)}+\underbrace{w^Tu^*_{D_k}(\mathbf x)-\int_0^1(1+x)\,u^*_{D_k}\,\mathrm dx}_{(2)}\qquad(k=0,1),\qquad \frac{\mathrm dJ_h}{\mathrm d\nu}=w^Tv_2.

项 (2)(2) 是梯形公式的误差(约为 (h2/12)(h^2/12) 乘以被积函数导数的端点差),项 (1)(1) 是图 48 里画出的切线误差按目标权重求和。两项之和与梯度误差相差 10−1510^{-15}(五个网格,aa、φ\varphi、ν\nu)。N=8N=8 时 aa 的误差 −0.0341−0.0341 里梯形公式只占 0.00750.0075,其余 −0.0415−0.0415 是切线误差;ν\nu 没有梯形项,dJh/dν\mathrm dJ_h/\mathrm d\nu 就是 v2v_2 的加权和。

Term (2)(2) is the error of the trapezoid rule (about (h2/12)(h^2/12) times the jump of the derivative of the integrand across the interval), term (1)(1) is the tangent error drawn in Figure 48, summed with the objective weights. The two terms add up to the gradient error to within 10−1510^{-15} (five meshes, aa, φ\varphi and ν\nu). At N=8N=8 the trapezoid rule is only 0.00750.0075 of the error −0.0341−0.0341 of aa; the rest, −0.0415−0.0415, is tangent error; ν\nu has no trapezoid term, and dJh/dν\mathrm dJ_h/\mathrm d\nu is the weighted sum of v2v_2.

梯度误差的切线视角(无限制器线性):切线误差的加权和与梯形公式的误差The tangent view of the gradient error (unlimited linear): the weighted tangent error and the error of the trapezoid rule
Naa:wT(v0−ua∗)w^T(v_0-u^*_a)aa: wT(v0−ua∗)w^T(v_0-u^*_a)aa:梯形aa: trapezoidaa:总aa: totalφ\varphi:wT(v1−uφ∗)w^T(v_1-u^*_\varphi)φ\varphi: wT(v1−uφ∗)w^T(v_1-u^*_\varphi)φ\varphi:梯形φ\varphi: trapezoidφ\varphi:总φ\varphi: total
8−4.2e−27.5e−3−3.4e−23.4e−1−4.4e−33.3e−1
161.2e−21.9e−31.4e−28.0e−2−1.1e−37.9e−2
324.9e−34.6e−45.3e−31.6e−2−2.7e−41.6e−2
641.1e−31.2e−41.2e−32.7e−3−6.8e−52.6e−3
1281.6e−42.9e−51.9e−42.8e−4−1.7e−52.6e−4

相位、振幅、黏性:什么在变

Phase, amplitude, viscosity: what changes

默认设计只是一个点。a→0a\to0 时基态是 U≡1U\equiv1,AA 与 φ\varphi 无关,而 RDe0R_De_0 对 cos⁡2πφ\cos2\pi\varphi 与 sin⁡2πφ\sin2\pi\varphi 是线性的,所以 dJh/da\mathrm dJ_h/\mathrm da 的误差恰好是 c0(N)cos⁡2πφ+c1(N)sin⁡2πφc_0(N)\cos2\pi\varphi+c_1(N)\sin2\pi\varphi,一条振幅为 C(N)=c02+c12C(N)=\sqrt{c_0^2+c_1^2} 的正弦(在 φ=0.13\varphi=0.13 处核对到 10−1510^{-15})。振幅 C(N)C(N) 是格式对这个波的分辨误差:格点格式 C(8)=0.287C(8)=0.287,C(16)=0.0691C(16)=0.0691,C(32)=0.0149C(32)=0.0149,C(64)=0.00263C(64)=0.00263(格心格式 0.311、0.176、0.099、0.049)。默认相位 φ=0.07\varphi=0.07 恰好落在误差的零点附近:N=8N=8 的误差 −0.0341−0.0341 只是 C(8)C(8) 的 12%。在 a=0.2a=0.2 把 φ\varphi 扫过一个周期(图 63),N=8N=8 时 aa 的梯度误差在 −0.437−0.437 与 0.2110.211 之间变化;对 41 个相位取均方根,格点格式与格心格式在 N=8N=8 时相当(aa:0.235 对 0.230;φ\varphi:0.272 对 0.281),ν\nu 则是格点格式更差(0.576 对 0.369)。从 N=16N=16 起格点格式在 aa、φ\varphi 上明显更好,N=64N=64 时好 18、18 倍;ν\nu 上 N=16N=16 时格点格式仍更差,N=32N=32 时相当,N=64N=64 时好 4.5 倍。

The default design is one point. For a→0a\to0 the base state is U≡1U\equiv1, AA does not depend on φ\varphi, and RDe0R_De_0 is linear in cos⁡2πφ\cos2\pi\varphi and sin⁡2πφ\sin2\pi\varphi, so the error of dJh/da\mathrm dJ_h/\mathrm da is exactly c0(N)cos⁡2πφ+c1(N)sin⁡2πφc_0(N)\cos2\pi\varphi+c_1(N)\sin2\pi\varphi, a sinusoid of amplitude C(N)=c02+c12C(N)=\sqrt{c_0^2+c_1^2} (checked at φ=0.13\varphi=0.13 to within 10−1510^{-15}). The amplitude C(N)C(N) is the resolution error of the scheme for this wave: for the node scheme C(8)=0.287C(8)=0.287, C(16)=0.0691C(16)=0.0691, C(32)=0.0149C(32)=0.0149, C(64)=0.00263C(64)=0.00263 (cell scheme 0.311, 0.176, 0.099, 0.049). The default phase φ=0.07\varphi=0.07 happens to lie near a zero of the error: the N=8N=8 error −0.0341−0.0341 is only 12% of C(8)C(8). Sweeping φ\varphi through one period at a=0.2a=0.2 (Figure 63), the error of the aa-gradient at N=8N=8 ranges from −0.437−0.437 to 0.2110.211; as a root mean square over 41 phases the node and the cell scheme are comparable at N=8N=8 (aa: 0.235 against 0.230; φ\varphi: 0.272 against 0.281) and the node scheme is worse for ν\nu (0.576 against 0.369). From N=16N=16 on the node scheme is clearly better for aa and φ\varphi, by factors 18 and 18 at N=64N=64; for ν\nu it is still worse at N=16N=16, equal at N=32N=32 and 4.5 times better at N=64N=64.

图 63 · 梯度误差随相位 φ 的变化(a=0.2,ν=0.01,无限制器线性;上排 a,下排 φ 的梯度误差;每图纵轴对称):格点格式(实线)与格心格式(灰虚线)。误差随 φ 近似按正弦变化,振幅随网格加密迅速减小;紫色虚线是默认相位 0.07:N=8 时它碰巧靠近格点格式误差的零点。格点格式(无限制器线性)格心格式默认相位 φ = 0.07−0.4−0.200.20.400.250.50.751φdJh​/da 的误差N = 8−0.2−0.100.10.200.250.50.751φN = 16−0.1−0.0500.050.100.250.50.751φN = 32−0.4−0.200.20.400.250.50.751φdJh​/dφ 的误差N = 8−0.2−0.100.10.200.250.50.751φN = 16−0.1−0.0500.050.100.250.50.751φN = 32
图 63 · 梯度误差随相位 φ\varphi 的变化(a=0.2a=0.2,ν=0.01\nu=0.01,无限制器线性;上排 aa,下排 φ\varphi 的梯度误差;每图纵轴对称):格点格式(实线)与格心格式(灰虚线)。误差随 φ\varphi 近似按正弦变化,振幅随网格加密迅速减小;紫色虚线是默认相位 0.070.07:N=8N=8 时它碰巧靠近格点格式误差的零点。
Figure 63 · The gradient errors against the phase φ (a=0.2, ν=0.01, unlimited linear; top row the error of the a-gradient, bottom row that of the φ-gradient; each panel symmetric): node scheme (solid) and cell scheme (grey dashed). The error is close to a sinusoid in φ and its amplitude falls quickly under refinement; the violet dashed line is the default phase 0.07, which at N=8 happens to lie near a zero of the node scheme's error.node scheme (unlimited linear)cell schemedefault phase φ = 0.07−0.4−0.200.20.400.250.50.751φerror of dJh​/daN = 8−0.2−0.100.10.200.250.50.751φN = 16−0.1−0.0500.050.100.250.50.751φN = 32−0.4−0.200.20.400.250.50.751φerror of dJh​/dφN = 8−0.2−0.100.10.200.250.50.751φN = 16−0.1−0.0500.050.100.250.50.751φN = 32
Figure 63 · The gradient errors against the phase φ\varphi (a=0.2a=0.2, ν=0.01\nu=0.01, unlimited linear; top row the error of the aa-gradient, bottom row that of the φ\varphi-gradient; each panel symmetric): node scheme (solid) and cell scheme (grey dashed). The error is close to a sinusoid in φ\varphi and its amplitude falls quickly under refinement; the violet dashed line is the default phase 0.070.07, which at N=8N=8 happens to lie near a zero of the node scheme's error.
梯度误差对 41 个相位的均方根(a=0.2a=0.2,ν=0.01\nu=0.01,无限制器线性)Root mean square of the gradient errors over 41 phases (a=0.2a=0.2, ν=0.01\nu=0.01, unlimited linear)
N格点 aanode aa格点 φ\varphinode φ\varphi格点 ν\nunode ν\nu格心 aacell aa格心 φ\varphicell φ\varphi格心 ν\nucell ν\nu
82.3e−12.7e−15.8e−12.3e−12.8e−13.7e−1
165.3e−26.4e−22.2e−11.3e−11.6e−11.5e−1
321.1e−21.4e−28.6e−27.5e−28.8e−28.7e−2
642.0e−32.4e−32.9e−23.7e−24.4e−21.3e−1

振幅与黏性的影响小得多。aa 从 0.050.05 变到 0.50.5(N=8N=8,φ=0.07\varphi=0.07),aa 的梯度误差只在 −0.037−0.037 到 −0.024−0.024 之间变化,φ\varphi 的误差近似与 aa 成正比(误差除以 aa 在 1.67 到 1.76 之间;连续梯度 asin⁡2πφa\sin2\pi\varphi 也与 aa 成正比)。ν\nu 从 0.0020.002 变到 0.10.1(N=8N=8):aa 的梯度误差在 −0.035−0.035 到 −0.002−0.002 之间,φ\varphi 的在 0.1000.100 到 0.3700.370 之间;ν≤0.02\nu\le0.02(层宽变化十倍)时 N=8N=8 的这两个误差只变化 9% 与 20%;只有 ν=0.05\nu=0.05 和 0.10.1(层宽是一个网格间距的 0.44 倍与 0.87 倍,uinh/ν=2.3u_{\rm in}h/\nu=2.3 与 1.11.1)时它们才明显变小。这并不能判定是否是未被分辨的层造成了这些误差:ν≤0.02\nu\le0.02 时层比一个网格间距薄至少 5.7 倍(uinh/ν≥5.7u_{\rm in}h/\nu\ge5.7),由这样的层造成的误差同样与 ν\nu 无关;ν=0.05\nu=0.05 和 0.10.1 时层仍比网格间距薄,但只薄 2.3 倍与 1.1 倍,网格 Péclet 数也随之改变,所以那里误差的减小无法归于两者之一。本节没有一个实验把层与粗网格上的其他误差分开。

Amplitude and viscosity matter much less. With aa from 0.050.05 to 0.50.5 (N=8N=8, φ=0.07\varphi=0.07) the error of the aa-gradient moves only between −0.037−0.037 and −0.024−0.024, and the error of the φ\varphi-gradient is nearly proportional to aa (the error divided by aa stays between 1.67 and 1.76; the continuous gradient asin⁡2πφa\sin2\pi\varphi is proportional to aa too). With ν\nu from 0.0020.002 to 0.10.1 (N=8N=8) the error of the aa-gradient moves between −0.035−0.035 and −0.002−0.002 and that of φ\varphi between 0.1000.100 and 0.3700.370; for ν≤0.02\nu\le0.02 (the layer width changes tenfold) these two N=8N=8 errors vary by only 9% and 20%; they fall markedly only at ν=0.05\nu=0.05 and 0.10.1, when the layer is 0.44 and 0.87 of an interval wide (uinh/ν=2.3u_{\rm in}h/\nu=2.3 and 1.11.1). This does not decide whether the unresolved layer causes these errors: for ν≤0.02\nu\le0.02 the layer is at least 5.7 times thinner than one interval (uinh/ν≥5.7u_{\rm in}h/\nu\ge5.7) and an error caused by such a layer would also be independent of ν\nu; at ν=0.05\nu=0.05 and 0.10.1 the layer is still thinner than the interval, but only by the factors 2.3 and 1.1, and the mesh Péclet number changes with it, so the fall of the errors there cannot be assigned to one of the two. No experiment of this section separates the layer from the other coarse-mesh errors.

边界重构的作用

The role of the boundary reconstruction

格点格式的两个边界节点用单侧差分 σ0=r0\sigma_0=r_0、σN=lN\sigma_N=l_N 做斜率。作为实验,把它们改成 σ0=σN=0\sigma_0=\sigma_N=0(边界节点不重构,像格心格式的端单元),其余语句、前向与反向代码都不变(这一行之外的 model.js 原样不动;audit/audit_d.py 用独立的实现重复了这个实验)。默认设计下 N=8N=8 时 aa 的梯度误差从 −0.034−0.034 变成 −0.671−0.671,N=64N=64 时从 1.2×10−31.2\times10^{-3} 变成 −5.3×10−2−5.3\times10^{-2},误差下降的观测阶(N=8N=8 到 512512,逐倍加密)是 1.20、1.19、1.28、1.45、1.63、1.78,只是缓慢地趋近二阶;标准格式的误差小得多,并在 N=16,1024N=16, 1024 处变号。这与格心页的端单元实验方向一致:边界旁的迹是一阶还是二阶,在两种格式里都主导粗网格上振幅梯度的误差。所以在默认设计上,格点格式的 aa 梯度误差小,依赖于它的边界节点做了二阶重构(以及上面扫相位看到的:默认相位靠近误差的零点),不需要层被分辨来解释。

The two boundary nodes of the node scheme take their slopes from one-sided differences, σ0=r0\sigma_0=r_0 and σN=lN\sigma_N=l_N. As an experiment, set σ0=σN=0\sigma_0=\sigma_N=0 instead (boundary nodes not reconstructed, like the end cells of the cell-centred scheme), with every other statement and the tangent and reverse code unchanged (model.js is otherwise untouched; audit/audit_d.py repeats the experiment with an independent implementation). At the default design the error of the aa-gradient goes from −0.034−0.034 to −0.671−0.671 at N=8N=8 and from 1.2×10−31.2\times10^{-3} to −5.3×10−2−5.3\times10^{-2} at N=64N=64, and the observed orders of its decay (successive doublings, N=8N=8 to 512512) are 1.20, 1.19, 1.28, 1.45, 1.63, 1.78, a slow approach to second order; the error of the standard scheme is much smaller and changes sign at N=16,1024N=16, 1024. This agrees in direction with the end-cell experiment of the cell-centred page: whether the traces next to the boundary are first- or second-order accurate dominates the coarse-mesh error of the amplitude gradient in both schemes. At the default design, then, the small aa-gradient error of the node scheme depends on the second-order reconstruction of its boundary nodes (and, as the phase sweep above shows, on the default phase lying near a zero of the error); a resolved layer is not needed to explain it.

图 64 · 边界节点是否重构(默认设计,无限制器线性;梯度误差的绝对值):格点格式(绿点)、同一格式但 σ_0=σ_N=0(紫方块,N=8 到 512)、格心格式(灰虚线)。不重构边界节点,格点格式在 a 上的误差与格心格式相当(N=8、64、512 时是格心格式的 1.96、1.07、0.87 倍),下降也慢得多。格点格式同一格式,σ0​ = σN​ = 0格心格式10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​18645124096Nk = 0:振幅 a10-7​10-6​10-5​10-4​10-3​10-2​10-1​18645124096Nk = 1:相位 φ10-7​10-6​10-5​10-4​10-3​10-2​10-1​18645124096Nk = 2:黏性 ν
图 64 · 边界节点是否重构(默认设计,无限制器线性;梯度误差的绝对值):格点格式(绿点)、同一格式但 σ0=σN=0\sigma_0=\sigma_N=0(紫方块,N=8N=8 到 512512)、格心格式(灰虚线)。不重构边界节点,格点格式在 aa 上的误差与格心格式相当(N=8N=8、6464、512512 时是格心格式的 1.96、1.07、0.87 倍),下降也慢得多。
Figure 64 · With and without reconstruction of the boundary nodes (default design, unlimited linear; absolute value of the gradient error): the node scheme (green dots), the same scheme with σ_0=σ_N=0 (violet squares, N=8 to 512), the cell scheme (grey dashed). Without the boundary reconstruction the node scheme's error for a is comparable with the cell scheme's (1.96, 1.07 and 0.87 times at N=8, 64 and 512) and decays much more slowly.node schemesame scheme, σ0​ = σN​ = 0cell scheme10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​18645124096Nk = 0: amplitude a10-7​10-6​10-5​10-4​10-3​10-2​10-1​18645124096Nk = 1: phase φ10-7​10-6​10-5​10-4​10-3​10-2​10-1​18645124096Nk = 2: viscosity ν
Figure 64 · With and without reconstruction of the boundary nodes (default design, unlimited linear; absolute value of the gradient error): the node scheme (green dots), the same scheme with σ0=σN=0\sigma_0=\sigma_N=0 (violet squares, N=8N=8 to 512512), the cell scheme (grey dashed). Without the boundary reconstruction the node scheme's error for aa is comparable with the cell scheme's (1.96, 1.07 and 0.87 times at N=8N=8, 6464 and 512512) and decays much more slowly.

局限。以上是数值观察,不是定理:只测了所写的网格(N=8N=8 到 40964096)、三种重构、φ\varphi 的一个周期、a=0.05a=0.05 到 0.50.5 与 ν=0.002\nu=0.002 到 0.20.2。“恰好是正弦”只对 a→0a\to0 严格成立(用 a=0a=0 的算例核对),在 a=0.2a=0.2 是近似;把粗网格误差说成“波没有被分辨”只是一个解读,没有单独测量;边界重构实验只改了边界节点的斜率一项,没有排除别的因素。上面的面板可以改 NN、重构、aa、φ\varphi、ν\nu 自己查看。

The limits. These are numerical observations, not theorems: only the meshes written (N=8N=8 to 40964096), the three reconstructions, one period of φ\varphi, a=0.05a=0.05 to 0.50.5 and ν=0.002\nu=0.002 to 0.20.2 were measured. “Exactly a sinusoid” holds strictly only for a→0a\to0 (checked with the a=0a=0 case) and is approximate at a=0.2a=0.2; saying that the coarse-mesh error means that “the wave is not resolved” is a reading that was not measured separately; the boundary experiment changes one thing, the slope of the boundary nodes, and does not exclude others. The panel above lets you change NN, the reconstruction, aa, φ\varphi and ν\nu and look for yourself.

黏性导数

The viscosity derivative

连续的 dJ/dν\mathrm dJ/\mathrm d\nu 精确为零,离散的却不为零。RDR_D 的 ν\nu 列有一个精确的形式:源项部分是

The continuous dJ/dν\mathrm dJ/\mathrm d\nu is exactly zero; the discrete one is not. The ν\nu column of RDR_D has an exact form: its source piece is

−(∂Qj∂ν−∂Qj−1∂ν)=ux∗(xj+1/2)−ux∗(xj−1/2),-\Bigl(\frac{\partial Q_j}{\partial\nu}-\frac{\partial Q_{j-1}}{\partial\nu}\Bigr)=u^*_x(x_{j+1/2})-u^*_x(x_{j-1/2}),

其通量部分是 −(Uj+1−2Uj+Uj−1)/h-(U_{j+1}-2U_j+U_{j-1})/h。记面上导数近似的误差

and its flux piece is −(Uj+1−2Uj+Uj−1)/h-(U_{j+1}-2U_j+U_{j-1})/h. With the error of the face gradient

Ef=Uf+1−Ufh−ux∗(xf+1/2),(RD)j2=−(Ej−Ej−1),dJhdν=ψTRDe2=∑f=0N−1Ef (ψ~f+1−ψ~f),ψ~0=ψ~N=0, ψ~j=ψj.E_f=\frac{U_{f+1}-U_f}{h}-u^*_x(x_{f+1/2}),\qquad (R_D)_{j2}=-\bigl(E_j-E_{j-1}\bigr),\qquad \frac{\mathrm dJ_h}{\mathrm d\nu}=\psi^TR_De_2=\sum_{f=0}^{N-1}E_f\,\bigl(\tilde\psi_{f+1}-\tilde\psi_f\bigr),\quad\tilde\psi_0=\tilde\psi_N=0,\ \tilde\psi_j=\psi_j.

(这里 EfE_f 与第 6 节的误差传播矩阵 EE 无关;ψ~\tilde\psi 把两个约束行的乘子置零——它们不含 ν\nu,所以不进入这个和。对 N=8N=8 逐行核对,差不到 10−1610^{-16};对六个网格核对求和公式,差不到 10−1610^{-16}。)若面上的导数近似等于精确导数,ν\nu 列就是零。dJh/dν\mathrm dJ_h/\mathrm d\nu 是面上导数近似的误差按伴随在该面的跳跃加权求和;伴随在入口层里跳得最厉害,所以从 N=16N=16 起几乎全部来自入口附近:xf+1/2≤0.05x_{f+1/2}\le0.05 的面在 N=16N=16 时贡献 91%,N=64N=64 时 98%,N=256N=256 时 100%(N=512N=512 时总和已低于 10−410^{-4},份额 102% 已没有意义);N=8N=8 时第一个面已在 x=0.0625x=0.0625,没有面落在 x≤0.05x\le0.05 内。连续问题里只有一个类比,不能算作印证:通量部分写成 ∫λxux∗ dx\int\lambda_xu^*_x\,\mathrm dx 时,−1.877−1.877 中有 −1.729−1.729 来自 x≤0.05x\le0.05;写成 −∫λuxx∗ dx-\int\lambda u^*_{xx}\,\mathrm dx 时,同一区间只给 +0.120+0.120——积分“来自哪里”取决于它的写法。

(Here EfE_f has nothing to do with the error propagator EE of Section 6; ψ~\tilde\psi sets the multipliers of the two constraint rows to zero, because they contain no ν\nu and do not enter this sum. Checked row by row for N=8N=8: the difference is below 10−1610^{-16}; the summation formula is checked on six meshes to within 10−1610^{-16}.) If the discrete face gradients were exact, the ν\nu column would vanish. dJh/dν\mathrm dJ_h/\mathrm d\nu is the sum of the face-gradient errors weighted by the jump of the adjoint across the face, and the adjoint jumps most inside the inlet layer, so from N=16N=16 on almost everything comes from next to the inlet: the faces with xf+1/2≤0.05x_{f+1/2}\le0.05 give 91% at N=16N=16, 98% at N=64N=64 and 100% at N=256N=256 (at N=512N=512 the total is already below 10−410^{-4} and the share, 102%, means little); at N=8N=8 the first face already lies at x=0.0625x=0.0625, so no face lies in x≤0.05x\le0.05. The continuous problem offers an analogy, not an agreement: written as ∫λxux∗ dx\int\lambda_xu^*_x\,\mathrm dx, the flux part takes −1.729−1.729 of its −1.877−1.877 from x≤0.05x\le0.05; written as −∫λuxx∗ dx-\int\lambda u^*_{xx}\,\mathrm dx, the same interval gives +0.120+0.120: where an integral comes from depends on how it is written.

数字。N=8N=8 时 dJh/dν=0.0039\mathrm dJ_h/\mathrm d\nu=0.0039 很小,但那是两个 O(1)O(1) 部分(2.1802.180 与 −2.176−2.176)的偶然抵消:N=16N=16 给出 −0.0698−0.0698,这是整个序列的峰值(绝对值),随后绝对值下降,逐倍加密(N=32N=32 到 10241024)的观测阶依次为 1.46、2.01、2.56、3.08、4.02——不是常数,因为误差正在走向变号——并在 N=1024N=1024 与 20482048 之间变号(从 −4.4×10−6−4.4\times10^{-6} 到 7.8×10−77.8\times10^{-7};N=4096N=4096 时是 4.4×10−74.4\times10^{-7})。图 65 显示两部分的收敛:源项部分从 N=32N=32 起与 1.8771.877 相差不到 1%(0.97%),通量部分从 N=64N=64 起如此(0.92%)。格心页上同一个量在 N=4096N=4096 时还有 7.9×10−47.9\times10^{-4},格点格式是 4.4×10−74.4\times10^{-7}。

The numbers. At N=8N=8, dJh/dν=0.0039\mathrm dJ_h/\mathrm d\nu=0.0039 is small, but only by an accidental cancellation of two parts of order one (2.1802.180 and −2.176−2.176): N=16N=16 gives −0.0698−0.0698, the peak of the whole sequence (in absolute value); afterwards its magnitude falls, with observed orders 1.46, 2.01, 2.56, 3.08, 4.02 over successive doublings (N=32N=32 to 10241024; not constant, because the error is approaching a sign change), and the sign changes between N=1024N=1024 and 20482048 (from −4.4×10−6−4.4\times10^{-6} to 7.8×10−77.8\times10^{-7}; 4.4×10−74.4\times10^{-7} at N=4096N=4096). Figure 65 shows the convergence of the two parts: the source part is within 1% of 1.8771.877 from N=32N=32 on (0.97%), the flux part from N=64N=64 on (0.92%). On the cell page the same quantity is still 7.9×10−47.9\times10^{-4} at N=4096N=4096; the node scheme has 4.4×10−74.4\times10^{-7}.

图 65 · 黏性导数的两部分(无限制器线性,默认设计)。左:通量部分(蓝)与源项部分(橙黄)趋向连续的 ∓ 1.877(虚线),圆点是它们的和 dJ_h/ dν。右:| dJ_h/ dν| 的双对数图,圈表示负值;虚线是斜率 -2 的参考线。N=8 的小值是偶然的抵消,不代表格式在 ν 上准。通量部分 ψT​ RD​flux​ e2​源项部分 ψT​ RD​src​ e2​dJh​/dν虚线:连续值 ∓1.877−2−10128645124096N两部分:通量(蓝)与源项(橙黄)10-7​10-6​10-5​10-4​10-3​10-2​10-1​18645124096N|dJh​/dν|:点为正,圈为负斜率 −2
图 65 · 黏性导数的两部分(无限制器线性,默认设计)。左:通量部分(蓝)与源项部分(橙黄)趋向连续的 ∓1.877\mp1.877(虚线),圆点是它们的和 dJh/dν\mathrm dJ_h/\mathrm d\nu。右:∣dJh/dν∣|\mathrm dJ_h/\mathrm d\nu| 的双对数图,圈表示负值;虚线是斜率 −2-2 的参考线。N=8N=8 的小值是偶然的抵消,不代表格式在 ν\nu 上准。
Figure 65 · The two parts of the viscosity derivative (unlimited linear, default design). Left: the flux part (blue) and the source part (amber) approach the continuous ∓ 1.877 (dashed); the dots are their sum dJ_h/ dν. Right: | dJ_h/ dν| on log–log axes, rings for negative values; the dashed line is a slope -2 guide. The small value at N=8 is an accidental cancellation and does not mean that the scheme is accurate in ν.flux part ψT​ RD​flux​ e2​source part ψT​ RD​src​ e2​dJh​/dνdashed: continuous ∓1.877−2−10128645124096Nthe two parts: flux (blue) and source (amber)10-7​10-6​10-5​10-4​10-3​10-2​10-1​18645124096N|dJh​/dν|: dots positive, rings negativeslope −2
Figure 65 · The two parts of the viscosity derivative (unlimited linear, default design). Left: the flux part (blue) and the source part (amber) approach the continuous ∓1.877\mp1.877 (dashed); the dots are their sum dJh/dν\mathrm dJ_h/\mathrm d\nu. Right: ∣dJh/dν∣|\mathrm dJ_h/\mathrm d\nu| on log–log axes, rings for negative values; the dashed line is a slope −2-2 guide. The small value at N=8N=8 is an accidental cancellation and does not mean that the scheme is accurate in ν\nu.

dJh/dν\mathrm dJ_h/\mathrm d\nu 随黏性的变化比较复杂。图 66 对六个 ν\nu 画出它随 NN 的变化:ν=0.002\nu=0.002 与 0.0050.005 时在 N=16N=16 到 10241024 的每个网格上都是负的;变为正值的网格随 ν\nu 增大而变粗(ν=0.02\nu=0.02:N=512N=512;ν=0.05\nu=0.05:N=64N=64;ν=0.1\nu=0.1:N=16N=16)。与格心页不同,它不只是网格 Péclet 数 uinh/νu_{\rm in}h/\nu 的函数:同一个 Péclet 数下 ν\nu 不同的点相差 34% 到 8.5 倍(13 组,每组 2 到 3 个点),所以这里没有给出按 Péclet 数的整理。

The dependence of dJh/dν\mathrm dJ_h/\mathrm d\nu on the viscosity is more complicated. Figure 66 plots it against NN for six values of ν\nu: for ν=0.002\nu=0.002 and 0.0050.005 it is negative on every mesh from N=16N=16 to 10241024; the first mesh on which it is positive moves to coarser meshes as ν\nu grows (ν=0.02\nu=0.02: N=512N=512; ν=0.05\nu=0.05: N=64N=64; ν=0.1\nu=0.1: N=16N=16). Unlike on the cell page it is not a function of the mesh Péclet number uinh/νu_{\rm in}h/\nu alone: points with the same Péclet number and different ν\nu differ by 34% up to a factor of 8.5 (13 groups of two or three points), so this page does not organise it by the Péclet number.

图 66 · | dJ_h/ dν| 随 N 的变化(无限制器线性,a=0.2,φ=0.07;每条线一个 ν,点为正、圈为负)。每个 ν 都收敛到零,但路径各不相同:符号会变,收敛前的峰值位置随 ν 移动。ν = 0.002ν = 0.005ν = 0.01ν = 0.02ν = 0.05ν = 0.1圈:负值10-6​10-5​10-4​10-3​10-2​10-1​1632641282565121024N|dJh​/dν|
图 66 · ∣dJh/dν∣|\mathrm dJ_h/\mathrm d\nu| 随 NN 的变化(无限制器线性,a=0.2a=0.2,φ=0.07\varphi=0.07;每条线一个 ν\nu,点为正、圈为负)。每个 ν\nu 都收敛到零,但路径各不相同:符号会变,收敛前的峰值位置随 ν\nu 移动。
Figure 66 · | dJ_h/ dν| against N (unlimited linear, a=0.2, φ=0.07; one line per ν, dots positive, rings negative). Every ν converges to zero, but along different paths: the sign changes, and the position of the peak before convergence moves with ν.ν = 0.002ν = 0.005ν = 0.01ν = 0.02ν = 0.05ν = 0.1rings: negative10-6​10-5​10-4​10-3​10-2​10-1​1632641282565121024N|dJh​/dν|
Figure 66 · ∣dJh/dν∣|\mathrm dJ_h/\mathrm d\nu| against NN (unlimited linear, a=0.2a=0.2, φ=0.07\varphi=0.07; one line per ν\nu, dots positive, rings negative). Every ν\nu converges to zero, but along different paths: the sign changes, and the position of the peak before convergence moves with ν\nu.

格点格式与格心格式:比较

Node against cell: the comparison

同一问题、同一设计、同一目标,两种格式的梯度放在一起。下表是 N=8N=8 的三种重构;下面是无限制器线性重构的误差随网格的变化。数字是在默认设计(φ=0.07\varphi=0.07)上量的;上一节说明了为什么一个设计不能代表全部。

The same problem, design and objective; the gradients of the two schemes side by side. The first table is N=8N=8 for the three reconstructions, the second the errors of unlimited linear reconstruction under refinement. The numbers are measured at the default design (φ=0.07\varphi=0.07); the previous subsection showed why one design does not represent them all.

N=8N=8 的梯度及其对连续精确值 (−0.144008, 0.085156, 0.000000)(−0.144008,\ 0.085156,\ 0.000000) 的误差:格点格式与格心格式(取自格心页)The gradients at N=8N=8 and their errors against the exact continuous values (−0.144008, 0.085156, 0.000000)(−0.144008,\ 0.085156,\ 0.000000): node scheme and cell scheme (from the cell-centred page)
重构Reconstruction分量Component格点:梯度node: gradient格点:误差node: error格心:梯度cell: gradient格心:误差cell: error
一阶first orderaa−1.175176−1.0312−0.745986−0.6020
一阶first orderφ\varphi−0.234594−0.3197−0.357342−0.4425
一阶first orderν\nu0.9925750.9926−0.245484−0.2455
无限制器线性unlimited linearaa−0.178061−0.0341−0.486650−0.3426
无限制器线性unlimited linearφ\varphi0.4199040.3347−0.061039−0.1462
无限制器线性unlimited linearν\nu0.0039090.0039−0.309871−0.3099
光滑限制器smooth limiteraa−0.188210−0.0442−0.656527−0.5125
光滑限制器smooth limiterφ\varphi0.5534680.4683−0.168097−0.2533
光滑限制器smooth limiterν\nu−0.315000−0.3150−0.290780−0.2908
梯度误差(无限制器线性,默认设计;格点格式与格心格式)Gradient errors (unlimited linear, default design; node scheme and cell scheme)
N格点 aanode aa格点 φ\varphinode φ\varphi格点 ν\nunode ν\nu格心 aacell aa格心 φ\varphicell φ\varphi格心 ν\nucell ν\nu
8−3.4e−23.3e−13.9e−3−3.4e−1−1.5e−1−3.1e−1
161.4e−27.9e−2−7.0e−2−2.1e−13.0e−2−8.7e−2
325.3e−31.6e−2−3.9e−2−1.1e−14.3e−29.5e−2
641.2e−32.6e−3−1.4e−2−4.9e−22.8e−21.8e−1
1281.9e−42.6e−4−3.5e−3−2.0e−21.4e−21.6e−1
2562.1e−5−1.5e−5−6.0e−4−6.8e−35.3e−38.5e−2
5127.7e−7−1.7e−5−7.1e−5−2.1e−31.7e−33.3e−2
1024−4.4e−7−6.0e−6−4.4e−6−5.8e−44.9e−41.0e−2
2048−1.9e−7−1.7e−67.8e−7−1.5e−41.3e−43.0e−3
4096−5.9e−8−4.6e−74.4e−7−3.9e−53.5e−57.9e−4

在默认设计上量到的事实:无限制器线性,N=8N=8 时格点格式的 aa 梯度误差是格心格式的 1/10,ν\nu 的 1/79,但 φ\varphi 是 2.3 倍(0.3350.335 对 −0.146−0.146)——相位梯度更差。从 N=32N=32 到 40964096,格点格式在三个分量上都更好:格心误差至少是格点误差的 20(aa)、2.7(φ\varphi)、2.4(ν\nu)倍。格点格式的误差在 N=16,1024N=16, 1024(aa)、N=256N=256(φ\varphi)、N=16,2048N=16, 2048(ν\nu)处变号,所以观测阶不规则,要到 N≥8192N\ge8192 才接近 2(独立 Python 实现的数据,附录 C:N=8192N=8192 到 1638416384 之间为 1.94、1.98、1.85);一阶重构:格点格式在 aa 上并不更好(每个网格上格心误差都是格点误差的 0.58–0.99 倍),在 φ\varphi 上只有 N=8,16N=8, 16 时更好(格心误差是格点误差的 0.19–11.26 倍),在 ν\nu 上从 N=16N=16 起更好(1.66–1945 倍;N=8N=8 时是 0.25 倍)。图 67 画出全部。

What was measured at the default design: for unlimited linear reconstruction the node scheme's aa-gradient error at N=8N=8 is 1/10 of the cell scheme's and its ν\nu error 1/79, but its φ\varphi error is 2.3 times as large (0.3350.335 against −0.146−0.146): the phase gradient is worse. From N=32N=32 to 40964096 the node scheme is better in all three components: the cell error is at least 20 (aa), 2.7 (φ\varphi) and 2.4 (ν\nu) times the node error. The node scheme's errors change sign at N=16,1024N=16, 1024 (aa), N=256N=256 (φ\varphi) and N=16,2048N=16, 2048 (ν\nu), so the observed orders are erratic and approach 2 only for N≥8192N\ge8192 (data of the independent Python implementation, Appendix C: 1.94, 1.98, 1.85 between N=8192N=8192 and 1638416384). For first-order reconstruction the node scheme is not better for aa (the cell error is 0.58–0.99 times the node error on every mesh), is better for φ\varphi only at N=8,16N=8, 16 (the cell error is 0.19–11.26 times the node error), and is better for ν\nu from N=16N=16 on (1.66–1945 times; 0.25 times at N=8N=8). Figure 67 draws all of it.

图 67 · 梯度误差的绝对值随 N 的变化(默认设计):格点格式与格心格式,无限制器线性与一阶重构。无限制器线性时格点格式从 N=32 起在三个分量上都更小;一阶重构时 a 上两种格式几乎重合;曲线上的凹口是误差经过零点(变号)处。格点,无限制器线性格心,无限制器线性格点,一阶格心,一阶10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​1108645124096Nk = 0:振幅 a10-7​10-6​10-5​10-4​10-3​10-2​10-1​18645124096Nk = 1:相位 φ10-7​10-6​10-5​10-4​10-3​10-2​10-1​18645124096Nk = 2:黏性 ν
图 67 · 梯度误差的绝对值随 NN 的变化(默认设计):格点格式与格心格式,无限制器线性与一阶重构。无限制器线性时格点格式从 N=32N=32 起在三个分量上都更小;一阶重构时 aa 上两种格式几乎重合;曲线上的凹口是误差经过零点(变号)处。
Figure 67 · The absolute gradient errors against N (default design): node and cell scheme, unlimited linear and first-order reconstruction. With unlimited linear reconstruction the node scheme is smaller in all three components from N=32 on; with first-order reconstruction the two schemes nearly coincide for a; the dips in the curves are where an error passes through zero (changes sign).node, unlimited linearcell, unlimited linearnode, first ordercell, first order10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​1108645124096Nk = 0: amplitude a10-7​10-6​10-5​10-4​10-3​10-2​10-1​18645124096Nk = 1: phase φ10-7​10-6​10-5​10-4​10-3​10-2​10-1​18645124096Nk = 2: viscosity ν
Figure 67 · The absolute gradient errors against NN (default design): node and cell scheme, unlimited linear and first-order reconstruction. With unlimited linear reconstruction the node scheme is smaller in all three components from N=32N=32 on; with first-order reconstruction the two schemes nearly coincide for aa; the dips in the curves are where an error passes through zero (changes sign).

光滑限制器在加密下的行为不同于无限制器线性。N=8N=8 时格点格式在 aa 上好 11.6 倍,在 φ\varphi 上差(格心误差是格点误差的 0.54 倍),在 ν\nu 上相当(0.92 倍);N=16N=16 与 3232 时 aa 上好 30 倍与 15 倍。但在细网格上这个优势消失:从 N=1024N=1024 起,aa 与 φ\varphi 上格心误差与格点误差之比只在 1.01–1.03 与 1.02–1.11 之间;N=4096N=4096 时格点格式的这两个误差分别是它自己一阶格式的误差的 98% 与 95%,在 N=2048N=2048 到 40964096 之间按一阶速度下降(观测阶 0.96 与 0.90)。ν\nu 的误差不同:N=4096N=4096 时是一阶格式的 3.2 倍,按 1.70 阶下降,是格心格式的 1.5 倍。图 68 画出三个分量;第 15 节研究三种重构的阶。

The smooth limiter behaves differently from unlimited linear under refinement. At N=8N=8 the node scheme is 11.6 times better for aa, worse for φ\varphi (the cell error is 0.54 times the node error) and comparable for ν\nu (0.92 times); at N=16N=16 and 3232 it is 30 and 15 times better for aa. On fine meshes the advantage disappears: from N=1024N=1024 on, the ratio of the cell error to the node error stays between 1.01 and 1.03 for aa and between 1.02 and 1.11 for φ\varphi; at N=4096N=4096 the node scheme's errors of the two components are 98% and 95% of those of its own first-order scheme, and they fall at the first-order rate between N=2048N=2048 and 40964096 (observed orders 0.96 and 0.90). The error of ν\nu is different: at N=4096N=4096 it is 3.2 times that of the first-order scheme, falls at order 1.70, and is 1.5 times the cell scheme's. Figure 68 draws the three components; Section 15 studies the orders of the three reconstructions.

图 68 · 光滑限制器的梯度误差绝对值随 N 的变化(默认设计):格点格式(紫点)、格心格式(灰虚线)和格点格式一阶重构的误差作参照(橙黄圈)。在 a 与 φ 上,细网格时三条曲线重合在一起:光滑限制器已经变成一阶格式;凹口是误差经过零点(变号)处。格点,光滑限制器格心,光滑限制器格点,一阶(参照)0.0010.010.11108645124096Nk = 0:振幅 a10-4​10-3​10-2​10-1​18645124096Nk = 1:相位 φ10-5​10-4​10-3​10-2​10-1​18645124096Nk = 2:黏性 ν
图 68 · 光滑限制器的梯度误差绝对值随 NN 的变化(默认设计):格点格式(紫点)、格心格式(灰虚线)和格点格式一阶重构的误差作参照(橙黄圈)。在 aa 与 φ\varphi 上,细网格时三条曲线重合在一起:光滑限制器已经变成一阶格式;凹口是误差经过零点(变号)处。
Figure 68 · The absolute gradient errors of the smooth limiter against N (default design): node scheme (violet dots), cell scheme (grey dashed), and the error of the node scheme with first-order reconstruction as a reference (amber rings). For a and φ the three curves run together on fine meshes: the smooth limiter has become a first-order scheme; the dips are where an error passes through zero (changes sign).node, smooth limitercell, smooth limiternode, first order (reference)0.0010.010.11108645124096Nk = 0: amplitude a10-4​10-3​10-2​10-1​18645124096Nk = 1: phase φ10-5​10-4​10-3​10-2​10-1​18645124096Nk = 2: viscosity ν
Figure 68 · The absolute gradient errors of the smooth limiter against NN (default design): node scheme (violet dots), cell scheme (grey dashed), and the error of the node scheme with first-order reconstruction as a reference (amber rings). For aa and φ\varphi the three curves run together on fine meshes: the smooth limiter has become a first-order scheme; the dips are where an error passes through zero (changes sign).

本节说明了这个误差来自哪里,也说明了什么不能说:它没有被证明是入口层造成的(ν\nu 从 0.0020.002 到 0.020.02 变化十倍,N=8N=8 的误差只变化 9%,未被分辨的层同样如此);逐控制体的项很大并互相抵消,净值只是小的余数,余数落在哪个控制体随 NN 与分量而变;它不取决于单个设计点(相位变化一周,误差变号),部分取决于边界节点的重构。第 15 节测量梯度怎样收敛,第 16 节系统地研究它与连续伴随的一致性。

This section showed where the error comes from, and what cannot be said: it is not shown to be caused by the inlet layer (a tenfold change of ν\nu, from 0.0020.002 to 0.020.02, moves the N=8N=8 error by only 9%, which an unresolved layer would also give); the per-volume terms are large and cancel, the net is a small remainder, and which volume carries the remainder changes with NN and with the component; it does not belong to one design point (the error changes sign over one period of the phase), and it depends in part on the reconstruction of the boundary nodes. Section 15 measures how the gradients converge, and Section 16 studies their consistency with the continuous adjoint systematically.

第 13 节Section 13

有限差分验证:每个扰动都重新求解

Finite-difference check: re-solve at every perturbed design

本节实验:先猜一猜,把步长 τ\tau 从 10−110^{-1} 一路缩到 10−1210^{-12},中心差分会不会越来越接近伴随梯度?在哪个 τ\tau 最准、能有几位有效数字一致?然后用本节的步长扫描实验检验。

Experiment: guess first: as the step τ\tau shrinks from 10−110^{-1} to 10−1210^{-12}, does the central difference keep getting closer to the adjoint gradient? At which τ\tau is it most accurate, and how many significant digits agree? Then test the guess with the step-scan lab of this section.

第 10、11 节用两种方法算出了离散目标的梯度:三个前向求解 Avk=−RDekAv_k=-R_De_k 给出 J˙=wTvk\dot J=w^Tv_k,一个伴随求解 ATψ=−gA^T\psi=-g 给出 Dˉ=RDTψ\bar D=R_D^T\psi;默认设计下三种重构的两组结果相差不超过 10−1410^{-14}。但这两条路都用到求导代码(第 8 节的前向语句和第 9 节的反向语句)。有限差分不对任何代码求导:它只在附近的设计上重新运行原始求解器。Newton 迭代解到舍入水平之后,它的值与 Newton 矩阵无关(本页的矩阵由前向语句生成,但不动点 R=0R=0 不依赖它),所以是对第 8–12 节的一次独立检验(下面的陷阱说明迭代没有收敛时会怎样)。

Sections 10 and 11 computed the gradient of the discrete objective in two ways: three tangent solves Avk=−RDekAv_k=-R_De_k give J˙=wTvk\dot J=w^Tv_k, and one adjoint solve ATψ=−gA^T\psi=-g gives Dˉ=RDTψ\bar D=R_D^T\psi; at the defaults the two differ by at most 10−1410^{-14} for all three reconstructions. Both paths use derivative code (the tangent statements of Section 8 and the reverse statements of Section 9). A finite difference differentiates no code: it only runs the primal solver again at nearby designs. Once Newton has converged to rounding its value does not depend on the Newton matrix (the page builds it from the tangent statements, but the fixed point R=0R=0 does not depend on it), so it is an independent check of Sections 8–12 (the traps below show what happens when the iteration is not converged).

Jh(D)=wT𝐔(D),R(𝐔(D),D)=0.J_h(D)=w^T\mathbf U(D),\qquad R\bigl(\mathbf U(D),D\bigr)=0.

被求导的函数是 Jh(D)J_h(D),即这套网格、这种重构下离散解的目标值(权重 wj=Wj(1+xj)w_j=W_j(1+x_j) 是梯形公式)。差分验证的是 ∂Jh/∂Dk\partial J_h/\partial D_k,不是连续问题的精确梯度。默认网格上两者相差很远:无限制器线性重构的伴随梯度是 (−0.178061, 0.419904, 0.003909)(-0.178061,\ 0.419904,\ 0.003909),精确梯度是 (−0.144008, 0.085156, 0)(-0.144008,\ 0.085156,\ 0)。这个差别是离散误差,第 15、16 节才讨论;本节只问一件事:伴随算出的数是不是 JhJ_h 的导数。

The function being differentiated is Jh(D)J_h(D), the objective of the discrete solution on this mesh with this reconstruction (the weights wj=Wj(1+xj)w_j=W_j(1+x_j) are the trapezoid rule). The finite difference checks ∂Jh/∂Dk\partial J_h/\partial D_k, not the exact gradient of the continuous problem. On the default mesh the two are far apart: the adjoint gradient with unlimited linear reconstruction is (−0.178061, 0.419904, 0.003909)(-0.178061,\ 0.419904,\ 0.003909), the exact gradient (−0.144008, 0.085156, 0)(-0.144008,\ 0.085156,\ 0). That difference is discretisation error, the subject of Sections 15 and 16; this section asks one thing only: is the number the adjoint computes the derivative of JhJ_h?

两个差商

Two difference quotients

记 ∂k=∂/∂Dk\partial_k=\partial/\partial D_k(第 13 至 15 节里下标 aa、φ\varphi、ν\nu 对应 k=0,1,2k=0,1,2:ea=e0e_a=e_0,va=v0v_a=v_0,Dˉa=Dˉ0\bar D_a=\bar D_0)。把 Jh(D±τek)J_h(D\pm\tau e_k) 在 DD 处做 Taylor 展开,单侧差商和中心差商分别是

Write ∂k=∂/∂Dk\partial_k=\partial/\partial D_k (in Sections 13 to 15 the subscripts aa, φ\varphi, ν\nu stand for k=0,1,2k=0,1,2: ea=e0e_a=e_0, va=v0v_a=v_0, Dˉa=Dˉ0\bar D_a=\bar D_0). Expanding Jh(D±τek)J_h(D\pm\tau e_k) in a Taylor series about DD gives the one-sided and the central quotient:

FDτ+=Jh(D+τek)−Jh(D)τ=∂kJh+τ2 ∂k2Jh+O(τ2),FDτc=Jh(D+τek)−Jh(D−τek)2τ=∂kJh+τ26 ∂k3Jh+O(τ4).\begin{aligned}\mathrm{FD}_\tau^+&=\frac{J_h(D+\tau e_k)-J_h(D)}{\tau}=\partial_kJ_h+\frac\tau2\,\partial_k^2J_h+O(\tau^2),\\ \mathrm{FD}_\tau^{\rm c}&=\frac{J_h(D+\tau e_k)-J_h(D-\tau e_k)}{2\tau}=\partial_kJ_h+\frac{\tau^2}6\,\partial_k^3J_h+O(\tau^4).\end{aligned}

中心差商里偶次项相减抵消,所以它的截断误差是二阶的。步长 τ\tau 只是一个数:它不是网格间距 hh,也不是导数记号。

In the central quotient the even powers cancel, so its truncation error is second order. The step τ\tau is just a number: it is neither the mesh spacing hh nor a derivative symbol.

每个扰动设计都要完整重新求解

Every perturbed design needs a full re-solve

Jh=wT𝐔J_h=w^T\mathbf U 本身不含 DD(第 7 节:JD=0J_D=0),设计只通过状态影响目标。所以只改 DD、不重新求解,差商就是 JD=0J_D=0,这就是“冻结状态”的错误。每个扰动设计 D±τekD\pm\tau e_k 都需要自己收敛的状态 𝐔(D±τek)\mathbf U(D\pm\tau e_k),网格、重构和 Newton 迭代都与基准求解相同(初值是扰动设计下 u∗u^* 在各节点的值,修正量不超过 10−1310^{-13} 时停止)。设计也改变边界数据:uin(D)u_{\rm in}(D)、uout(D)u_{\rm out}(D) 进入两个约束行 R0R_0、RNR_N,所以两个边界节点的值也随 aa、φ\varphi 一起动。图 69 上图是改变振幅后的状态;下图说明状态差商 [𝐔(D+τea)−𝐔(D)]/τ[\mathbf U(D+\tau e_a)-\mathbf U(D)]/\tau 随 τ→0\tau\to0 趋向第 10 节的切线解 va=𝐔˙v_a=\dot{\mathbf U}:τ=0.1\tau=0.1、0.010.01、0.0010.001 时最大偏差为 5.3×10−35.3\times10^{-3}、5.2×10−45.2\times10^{-4}、5.2×10−55.2\times10^{-5},相邻两次之比为 10.2 和 10.0,约 10 倍(一阶)。在两个边界节点上偏差只有舍入:约束行对 aa 是线性的,差商恰好等于 duin/da=−sin⁡ 2πφ\mathrm du_{\rm in}/\mathrm da=-\sin\,2\pi\varphi(最大偏差不超过 10−1310^{-13})。

Jh=wT𝐔J_h=w^T\mathbf U contains no DD of its own (Section 7: JD=0J_D=0); the design acts on the objective only through the state. Change DD without solving again and the quotient is JD=0J_D=0: the "frozen state" bug. Every perturbed design D±τekD\pm\tau e_k needs its own converged state 𝐔(D±τek)\mathbf U(D\pm\tau e_k), with the mesh, the reconstruction and the Newton iteration of the base solve (started from the values of u∗u^* at the nodes of the perturbed design, stopped when the correction is at most 10−1310^{-13}). The design also changes the boundary data: uin(D)u_{\rm in}(D) and uout(D)u_{\rm out}(D) enter the two constraint rows R0R_0 and RNR_N, so the two boundary nodes move with aa and φ\varphi too. The top panel of Figure 69 shows the state after a change of the amplitude; the bottom panel shows the state quotient [𝐔(D+τea)−𝐔(D)]/τ[\mathbf U(D+\tau e_a)-\mathbf U(D)]/\tau approaching the tangent solution va=𝐔˙v_a=\dot{\mathbf U} of Section 10 as τ→0\tau\to0: the largest deviation is 5.3×10−35.3\times10^{-3}, 5.2×10−45.2\times10^{-4} and 5.2×10−55.2\times10^{-5} for τ=0.1\tau=0.1, 0.010.01 and 0.0010.001, smaller by factors of 10.2 and 10.0: about 10 each time (first order). At the two boundary nodes the deviation is rounding only: the constraint rows are linear in aa, so the quotient is exactly duin/da=−sin⁡ 2πφ\mathrm du_{\rm in}/\mathrm da=-\sin\,2\pi\varphi (largest deviation at most 10−1310^{-13}).

图 69 · 扰动设计必须重新求解(默认设计,N=8,无限制器线性)。上:U(D)(点)与 U(D+0.1 e_a)(圈)——整个状态都变了,两个端点也变了。下:状态差商(τ=0.1 圈,τ=0.01 方块)趋向切线解 v_a(实线),在两个端点上与它重合;差分在目标上看到的变化 w^Tv_a 就来自这里。0.80.911.11.200.20.40.60.81xUj​U(D)U(D + τ ea​),τ = 0.1−0.500.500.20.40.60.81x状态差商[U(D + τea​) − U(D)]/τ, τ = 0.1τ = 0.01切线解 va​(第 10 节)
图 69 · 扰动设计必须重新求解(默认设计,N=8N=8,无限制器线性)。上:𝐔(D)\mathbf U(D)(点)与 𝐔(D+0.1 ea)\mathbf U(D+0.1\,e_a)(圈)——整个状态都变了,两个端点也变了。下:状态差商(τ=0.1\tau=0.1 圈,τ=0.01\tau=0.01 方块)趋向切线解 vav_a(实线),在两个端点上与它重合;差分在目标上看到的变化 wTvaw^Tv_a 就来自这里。
Figure 69 · A perturbed design must be solved again (default design, N=8, unlimited linear). Top: U(D) (dots) and U(D+0.1 e_a) (rings): the whole state changes, the two end nodes included. Bottom: the state quotients (τ=0.1 rings, τ=0.01 squares) approach the tangent solution v_a (solid line) and coincide with it at the two end nodes; the change w^Tv_a that the difference quotient sees in the objective comes from here.0.80.911.11.200.20.40.60.81xUj​U(D)U(D + τ ea​), τ = 0.1−0.500.500.20.40.60.81xstate quotient[U(D + τea​) − U(D)]/τ, τ = 0.1τ = 0.01tangent solution va​ (Section 10)
Figure 69 · A perturbed design must be solved again (default design, N=8N=8, unlimited linear). Top: 𝐔(D)\mathbf U(D) (dots) and 𝐔(D+0.1 ea)\mathbf U(D+0.1\,e_a) (rings): the whole state changes, the two end nodes included. Bottom: the state quotients (τ=0.1\tau=0.1 rings, τ=0.01\tau=0.01 squares) approach the tangent solution vav_a (solid line) and coincide with it at the two end nodes; the change wTvaw^Tv_a that the difference quotient sees in the objective comes from here.

完整的验证流程如下(伪代码;本页的扫描实验就是这样算的):

The complete check reads (pseudocode; the step-scan lab of this page computes exactly this):

U0 = solve(D)                          # Newton:初值 u*(x_j; D),修正量 |dU| <= 1e-13 时停止
J0 = w . U0
for k in (a, phi, nu):
    for tau in 1e-1, 1e-2, ..., 1e-12:
        Up = solve(D + tau e_k)        # 完整的重新求解:状态会变
        Um = solve(D - tau e_k)        # 对 nu 只在 nu - tau > 0 时
        FD_f = (w . Up - J0) / tau
        FD_c = (w . Up - w . Um) / (2 tau)
        与 Dbar_k = (R_D^T psi)_k 比较     # 第 11 节的伴随梯度
U0 = solve(D)                          # Newton: initial guess u*(x_j; D), stop when |dU| <= 1e-13
J0 = w . U0
for k in (a, phi, nu):
    for tau in 1e-1, 1e-2, ..., 1e-12:
        Up = solve(D + tau e_k)        # a full re-solve: the state changes
        Um = solve(D - tau e_k)        # for nu only if nu - tau > 0
        FD_f = (w . Up - J0) / tau
        FD_c = (w . Up - w . Um) / (2 tau)
        compare with Dbar_k = (R_D^T psi)_k     # the adjoint gradient of Section 11

一次中心差分要 2 次非线性求解,三个分量 6 次;扫描 12 个步长最多 72 次(ν−τ≤0\nu-\tau\le0 的点不算),再加 1 次基准求解。伴随只要 1 次线性求解就给出全部三个分量(第 11 节)。这里设计只有 3 个分量,差分的负担不重;设计有成千上万个分量时,差分只能抽查少数几个方向(下面的实验可以选一个混合方向)。

One central difference costs 2 nonlinear solves, 6 for the three components; a scan over 12 steps costs up to 72 (the points with ν−τ≤0\nu-\tau\le0 are skipped), plus the base solve. The adjoint gives all three components with one linear solve (Section 11). With 3 design components the finite differences are affordable here; with thousands of components they can only spot-check a few directions (the lab below can pick a mixed direction).

截断误差与舍入误差:V 形

Truncation against rounding: the V

两种误差相互竞争。截断误差随 τ\tau 减小(单侧差商斜率 1,中心差商斜率 2)。舍入误差正相反:JhJ_h 只有约 16 位有效数字,它的舍入误差 εJ≈εmach∣Jh∣\varepsilon_J\approx\varepsilon_{\rm mach}|J_h| 不随 τ\tau 变小,差商却要把它除以 τ\tau:

Two errors compete. The truncation error shrinks with τ\tau (slope 1 for the one-sided quotient, slope 2 for the central one). The rounding error does the opposite: JhJ_h carries about 16 significant digits, its rounding error εJ≈εmach∣Jh∣\varepsilon_J\approx\varepsilon_{\rm mach}|J_h| does not shrink with τ\tau, and the quotient divides it by τ\tau:

∣FDτc−∂kJh∣≈τ26 ∣∂k3Jh∣+εJτ,εJ≈εmach∣Jh∣,εmach=2.2×10−16.\bigl|\mathrm{FD}_\tau^{\rm c}-\partial_kJ_h\bigr|\approx\frac{\tau^2}6\,\bigl|\partial_k^3J_h\bigr|+\frac{\varepsilon_J}\tau,\qquad \varepsilon_J\approx\varepsilon_{\rm mach}|J_h|,\quad \varepsilon_{\rm mach}=2.2\times10^{-16}.

在双对数图上右支是斜率 2 的直线,左支是斜率 −1-1 的直线,合起来是一个 V 形。令两项之和对 τ\tau 的导数为零,得到最佳步长 τopt=(3εJ/∣∂k3Jh∣)1/3\tau_{\rm opt}=(3\varepsilon_J/|\partial_k^3J_h|)^{1/3}。这些高阶导数可以由伴随梯度差分得到:在 DD 两侧各做一次伴随求解(步长是 10−410^{-4};差分的是精确导数,不是目标值),两侧梯度的中心差分是 ∂k2Jh\partial_k^2J_h,再用上 DD 处的梯度做二阶差分得到 ∂k3Jh\partial_k^3J_h。默认设计下对 aa 得 ∂a2Jh=0.0205\partial_a^2J_h=0.0205、∂a3Jh=0.0052\partial_a^3J_h=0.0052,于是 τopt≈5.7×10−5\tau_{\rm opt}\approx5.7\times10^{-5},最小误差约 8.5×10−128.5\times10^{-12}。扫描中实际最好的是 τ=10−4\tau=10^{-4},误差不到 3×10−113\times10^{-11}。图 70 把预测线和实测点画在一起。

On log-log axes the right branch is a line of slope 2 and the left branch a line of slope −1-1: together they form a V. Setting the derivative of the sum to zero gives the best step τopt=(3εJ/∣∂k3Jh∣)1/3\tau_{\rm opt}=(3\varepsilon_J/|\partial_k^3J_h|)^{1/3}. The higher derivatives come from differencing the adjoint gradient: one adjoint solve on each side of DD (with the step 10−410^{-4}; what is differenced is an exact derivative, not the objective); the central difference of the two gradients is ∂k2Jh\partial_k^2J_h, and the second difference with the gradient at DD is ∂k3Jh\partial_k^3J_h. At the defaults this gives ∂a2Jh=0.0205\partial_a^2J_h=0.0205 and ∂a3Jh=0.0052\partial_a^3J_h=0.0052 for the amplitude, so τopt≈5.7×10−5\tau_{\rm opt}\approx5.7\times10^{-5} and a smallest error of about 8.5×10−128.5\times10^{-12}. The best point of the actual scan is τ=10−4\tau=10^{-4}, with an error below 3×10−113\times10^{-11}. Figure 70 draws the predicted lines and the measured points together.

图 70 · V 形是可以预测的(分量 a,默认设计,无限制器线性)。方块和圈是实测的中心与单侧差分误差;两条虚线是 Taylor 预测的截断误差 τ^2|∂_a^3J_h|/6 与 τ|∂_a^2J_h|/2(导数由伴随梯度再差分得到);灰色点线是舍入线 ε_mach|J_h|/τ。τ=10^(-3) 时,实测与预测之比:中心差分与 1 相差不到 10^(-3),单侧差分是 1.0001。10-12​10-11​10-10​10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-12​10-10​10-8​10-6​10-4​10-2​步长 τ|差商 − 伴随梯度|舍入线 εmach​|Jh​|/τ分量 a:实测误差与两条预测线单侧差分 FD+​中心差分 FDc​
图 70 · V 形是可以预测的(分量 aa,默认设计,无限制器线性)。方块和圈是实测的中心与单侧差分误差;两条虚线是 Taylor 预测的截断误差 τ2∣∂a3Jh∣/6\tau^2|\partial_a^3J_h|/6 与 τ∣∂a2Jh∣/2\tau|\partial_a^2J_h|/2(导数由伴随梯度再差分得到);灰色点线是舍入线 εmach∣Jh∣/τ\varepsilon_{\rm mach}|J_h|/\tau。τ=10−3\tau=10^{-3} 时,实测与预测之比:中心差分与 1 相差不到 10−310^{-3},单侧差分是 1.0001。
Figure 70 · The V can be predicted (component a, default design, unlimited linear). Squares and rings are the measured central and one-sided errors; the two dashed lines are the Taylor predictions of the truncation error, τ^2|∂_a^3J_h|/6 and τ|∂_a^2J_h|/2 (the derivatives from differencing the adjoint gradient); the dotted grey line is the rounding line ε_mach|J_h|/τ. At τ=10^(-3) the measured over the predicted error differs from 1 by less than 10^(-3) (central), and is 1.0001 (one-sided).10-12​10-11​10-10​10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-12​10-10​10-8​10-6​10-4​10-2​step τ|quotient − adjoint gradient|rounding εmach​|Jh​|/τcomponent a: measured errors and the two predicted linesone-sided FD+​central FDc​
Figure 70 · The V can be predicted (component aa, default design, unlimited linear). Squares and rings are the measured central and one-sided errors; the two dashed lines are the Taylor predictions of the truncation error, τ2∣∂a3Jh∣/6\tau^2|\partial_a^3J_h|/6 and τ∣∂a2Jh∣/2\tau|\partial_a^2J_h|/2 (the derivatives from differencing the adjoint gradient); the dotted grey line is the rounding line εmach∣Jh∣/τ\varepsilon_{\rm mach}|J_h|/\tau. At τ=10−3\tau=10^{-3} the measured over the predicted error differs from 1 by less than 10−310^{-3} (central), and is 1.0001 (one-sided).

图 71 对三个分量各做一次扫描。右支都贴着斜率 1、2 的参考线:τ=10−3\tau=10^{-3} 时,实测中心差分误差与预测 τ2∣∂k3Jh∣/6\tau^2|\partial_k^3J_h|/6 之比与 1 的偏差,对 aa、φ\varphi、ν\nu 三个分量都小于 10−310^{-3}。左支沿着舍入线上升:τ≤10−8\tau\le10^{-8} 的中心差分点没有一个高过舍入线的 2 倍(它们落在舍入线的 0.01 到 1.1 倍之间,因为 JhJ_h 的舍入误差会部分抵消)。三个分量的右支高度差得很远,因为三阶导数差得很远:无限制器线性的 ∂a3Jh=0.0052\partial_a^3J_h=0.0052,而 ∂φ3Jh=−13.40\partial_\varphi^3J_h=-13.40、∂ν3Jh=−39.36\partial_\nu^3J_h=-39.36。所以 aa 的 V 形谷底在 τ=10−4\tau=10^{-4},φ\varphi 和 ν\nu 的在 τ=10−6\tau=10^{-6}。ν=0.01\nu=0.01 很小,τ≥ν\tau\ge\nu 时 ν−τ≤0\nu-\tau\le0,中心差分根本不能用,图和表里没有这些点。

Figure 71 scans each of the three components. All right branches follow the reference lines of slopes 1 and 2: at τ=10−3\tau=10^{-3} the measured central error over the prediction τ2∣∂k3Jh∣/6\tau^2|\partial_k^3J_h|/6 differs from 1 by less than 10−310^{-3} for all three components aa, φ\varphi, ν\nu. The left branches rise along the rounding line: no central-difference point with τ≤10−8\tau\le10^{-8} lies above 2 times it (the points lie between 0.01 and 1.1 times it, because the rounding errors of JhJ_h partly cancel). The heights of the three right branches are very different because the third derivatives are: for unlimited linear ∂a3Jh=0.0052\partial_a^3J_h=0.0052, but ∂φ3Jh=−13.40\partial_\varphi^3J_h=-13.40 and ∂ν3Jh=−39.36\partial_\nu^3J_h=-39.36. So the bottom of the V of aa is at τ=10−4\tau=10^{-4}, and that of φ\varphi and ν\nu at τ=10−6\tau=10^{-6}. ν=0.01\nu=0.01 is small, and for τ≥ν\tau\ge\nu the central difference cannot even be formed (ν−τ≤0\nu-\tau\le0), so those points are missing from the figure and the tables.

图 71 · 三个分量的步长扫描(默认设计,N=8,无限制器线性)。圈:单侧差分;方块:中心差分;虚线:斜率 1、2 的参考线;点线:舍入线 ε_mach|J_h|/τ。每个分量的 V 形谷底不同:中心差分的最佳步长分别是 10^(-4)、10^(-6)、10^(-6),预测的最小误差 E_opt 分别约为 8.5 × 10^(-12)、1.2 × 10^(-10)、1.7 × 10^(-10)(实测的最小误差在这个量级,见下表)。10-12​10-11​10-10​10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-12​10-10​10-8​10-6​10-4​10-2​步长 τ|差商 − 伴随梯度|舍入线 εmach​|Jh​|/τ21分量 a:∂Jh​/∂a = −0.178061单侧差分 FD+​中心差分 FDc​10-11​10-10​10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​10-12​10-10​10-8​10-6​10-4​10-2​步长 τ|差商 − 伴随梯度|舍入线 εmach​|Jh​|/τ21分量 φ:∂Jh​/∂φ = 0.419904单侧差分 FD+​中心差分 FDc​10-11​10-10​10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​110-12​10-10​10-8​10-6​10-4​10-2​步长 τ|差商 − 伴随梯度|舍入线 εmach​|Jh​|/τ21分量 ν:∂Jh​/∂ν = 0.003909单侧差分 FD+​中心差分 FDc​
图 71 · 三个分量的步长扫描(默认设计,N=8N=8,无限制器线性)。圈:单侧差分;方块:中心差分;虚线:斜率 1、2 的参考线;点线:舍入线 εmach∣Jh∣/τ\varepsilon_{\rm mach}|J_h|/\tau。每个分量的 V 形谷底不同:中心差分的最佳步长分别是 10−410^{-4}、10−610^{-6}、10−610^{-6},预测的最小误差 EoptE_{\rm opt} 分别约为 8.5×10−128.5\times10^{-12}、1.2×10−101.2\times10^{-10}、1.7×10−101.7\times10^{-10}(实测的最小误差在这个量级,见下表)。
Figure 71 · The step scans of the three components (default design, N=8, unlimited linear). Rings: one-sided differences; squares: central differences; dashed: reference lines of slopes 1 and 2; dotted: the rounding line ε_mach|J_h|/τ. The bottom of the V differs from component to component: the best central steps are 10^(-4), 10^(-6), 10^(-6), and the predicted smallest error E_opt is about 8.5 × 10^(-12), 1.2 × 10^(-10), 1.7 × 10^(-10) (the measured smallest errors are of that size; see the table below).10-12​10-11​10-10​10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-12​10-10​10-8​10-6​10-4​10-2​step τ|quotient − adjoint gradient|rounding εmach​|Jh​|/τ21component a: ∂Jh​/∂a = −0.178061one-sided FD+​central FDc​10-11​10-10​10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​10-12​10-10​10-8​10-6​10-4​10-2​step τ|quotient − adjoint gradient|rounding εmach​|Jh​|/τ21component φ: ∂Jh​/∂φ = 0.419904one-sided FD+​central FDc​10-11​10-10​10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​110-12​10-10​10-8​10-6​10-4​10-2​step τ|quotient − adjoint gradient|rounding εmach​|Jh​|/τ21component ν: ∂Jh​/∂ν = 0.003909one-sided FD+​central FDc​
Figure 71 · The step scans of the three components (default design, N=8N=8, unlimited linear). Rings: one-sided differences; squares: central differences; dashed: reference lines of slopes 1 and 2; dotted: the rounding line εmach∣Jh∣/τ\varepsilon_{\rm mach}|J_h|/\tau. The bottom of the V differs from component to component: the best central steps are 10−410^{-4}, 10−610^{-6}, 10−610^{-6}, and the predicted smallest error EoptE_{\rm opt} is about 8.5×10−128.5\times10^{-12}, 1.2×10−101.2\times10^{-10}, 1.7×10−101.7\times10^{-10} (the measured smallest errors are of that size; see the table below).

下表是三种重构、三个分量的中心差分误差 ∣FDτc−Dˉk∣|\mathrm{FD}_\tau^{\rm c}-\bar D_k|(Dˉk\bar D_k 是第 11 节的伴随梯度),粗体是每一列的最小值(接近舍入线的最佳误差随算术实现可差到 10 倍,只应按数量级引用):

The table lists the central-difference errors ∣FDτc−Dˉk∣|\mathrm{FD}_\tau^{\rm c}-\bar D_k| for the three reconstructions and components (Dˉk\bar D_k is the adjoint gradient of Section 11); bold is the smallest value of each column (entries near the rounding line change with the arithmetic by up to a factor 10: quote them by order of magnitude only):

一阶first order无限制器线性unlimited linear光滑限制器smooth limiter
τ\tauaaφ\varphiν\nuaaφ\varphiν\nuaaφ\varphiν\nu
10−110^{-1}5.6e−31.1e−2—9.3e−62.2e−2—9.9e−57.4e−2—
10−210^{-2}5.5e−51.1e−4—8.7e−82.2e−4—2.7e−76.2e−3—
10−310^{-3}5.5e−71.1e−61.1e−58.7e−102.2e−66.6e−62.8e−96.0e−52.8e−5
10−410^{-4}5.5e−91.1e−81.1e−76.6e−122.2e−86.6e−82.9e−116.0e−72.8e−7
10−510^{-5}5.1e−111.2e−101.1e−99.9e−122.4e−106.5e−105.3e−126.0e−92.8e−9
10−610^{-6}1.4e−101.4e−101.2e−119.0e−118.5e−115.9e−111.2e−102.7e−101.9e−10
10−710^{-7}1.5e−95.3e−108.8e−102.6e−96.9e−103.9e−105.5e−101.5e−92.3e−9
10−810^{-8}8.1e−91.6e−81.1e−81.5e−94.9e−92.9e−91.6e−81.5e−81.2e−8
10−910^{-9}8.6e−83.9e−86.7e−82.5e−71.6e−88.1e−81.0e−71.1e−71.6e−7
10−1010^{-10}1.5e−68.2e−74.4e−82.5e−72.4e−71.4e−62.4e−65.5e−78.2e−7
重构Reconstruction分量Component伴随梯度 Dˉk\bar D_kAdjoint gradient Dˉk\bar D_k中心差分最佳 τ\tauBest central τ\tau误差Error单侧差分最佳 τ\tauBest one-sided τ\tau误差Error
一阶first orderaa−1.17517610−510^{-5}5.1e−1110−810^{-8}1.9e−8
一阶first orderφ\varphi−0.23459410−510^{-5}1.2e−1010−810^{-8}4.9e−8
一阶first orderν\nu0.99257510−610^{-6}1.2e−1110−810^{-8}2.3e−10
无限制器线性unlimited linearaa−0.17806110−410^{-4}6.6e−1210−710^{-7}1.5e−9
无限制器线性unlimited linearφ\varphi0.41990410−610^{-6}8.5e−1110−810^{-8}1.6e−8
无限制器线性unlimited linearν\nu0.00390910−610^{-6}5.9e−1110−810^{-8}3.0e−8
光滑限制器smooth limiteraa−0.18821010−510^{-5}5.3e−1210−710^{-7}8.3e−9
光滑限制器smooth limiterφ\varphi0.55346810−610^{-6}2.7e−1010−810^{-8}6.3e−8
光滑限制器smooth limiterν\nu−0.31500010−610^{-6}1.9e−1010−810^{-8}2.3e−8

读表:中心差分在最佳步长处与伴随梯度相差 10−1210^{-12} 到 10−910^{-9},这些梯度有 7 到 10 位有效数字一致;单侧差分的最佳误差是 10−1010^{-10} 到 10−710^{-7}。最佳步长因分量和重构而异,事先并不知道,所以只算一个 τ\tau 的差分不够,要扫描。常用的折中 τ=10−5\tau=10^{-5} 在九个序列上给出的误差最大是 6.0×10−96.0\times10^{-9},出在光滑限制器的 φ\varphi 分量(它的三阶导数 ∂φ3Jh=361.4\partial_\varphi^3J_h=361.4 最大):九个序列里至少有 6 个的误差与预测的截断项 τ2∣∂k3Jh∣/6\tau^2|\partial_k^3J_h|/6 相差不到 20%,其余的接近舍入水平(其中有两个 aa 分量:无限制器线性和光滑限制器,它们的三阶导数很小)。这个步长对 ν\nu 也要小心:τ/ν=10−3\tau/\nu=10^{-3}。

Reading the tables: at its best step the central difference differs from the adjoint gradient by 10−1210^{-12} to 10−910^{-9}, so 7 to 10 significant digits of these gradients agree; the best one-sided errors are 10−1010^{-10} to 10−710^{-7}. The best step differs by component and reconstruction and is not known in advance, so a difference at one τ\tau is not enough: scan. The common compromise τ=10−5\tau=10^{-5} gives a largest error of 6.0×10−96.0\times10^{-9} on the nine series, in the φ\varphi-component of the smooth limiter (which has the largest third derivative, ∂φ3Jh=361.4\partial_\varphi^3J_h=361.4): at least 6 of the nine have an error within 20% of the predicted truncation term τ2∣∂k3Jh∣/6\tau^2|\partial_k^3J_h|/6, and the others are near rounding level (they include the two aa-components, unlimited linear and smooth limiter, whose third derivatives are tiny). The step needs care for ν\nu too: τ/ν=10−3\tau/\nu=10^{-3}.

自己扫一遍:改变上方的网格、重构或设计(点“求解并更新”),选一个分量,看 V 形怎样移动;也可以选一个混合方向 d=(1,0.3,0)d=(1,0.3,0),用一对差分检验整个梯度在这个方向上的分量 Dˉ⋅d\bar D\cdot d。

Scan it yourself: change the mesh, the reconstruction or the design above (press Solve & update), pick a component and watch the V move; or pick the mixed direction d=(1,0.3,0)d=(1,0.3,0), where one pair of differences checks the whole gradient along that direction, Dˉ⋅d\bar D\cdot d.

割线如何变成切线

How the secant turns into the tangent

单侧差商 FDτ+\mathrm{FD}_\tau^+ 有一个几何意义:它是曲线 t↦Jh(D+tek)t\mapsto J_h(D+te_k) 上过 t=0t=0 与 t=τt=\tau 两点的割线的斜率;切线的斜率是 ∂kJh\partial_kJ_h,也就是伴随给出的 Dˉk\bar D_k。下面的播放器把 τ\tau 每步缩小 10 倍:前两步割线与切线还看得出区别(在放大图里;主图里只有 ν\nu 分量看得出,aa、φ\varphi 分量在 τ=0.1\tau=0.1 时已经重合:斜率只差 0.6% 与 1.9%),之后在图上已经重合,差别只留在数字里——看一致的有效数字位数先增后减。

The one-sided quotient FDτ+\mathrm{FD}_\tau^+ has a geometric meaning: it is the slope of the secant through the points t=0t=0 and t=τt=\tau of the curve t↦Jh(D+tek)t\mapsto J_h(D+te_k); the slope of the tangent is ∂kJh\partial_kJ_h, the Dˉk\bar D_k of the adjoint. The player below divides τ\tau by 10 at every step: for the first two steps the secant and the tangent can still be told apart (in the zoomed panel; in the main panel only for ν\nu, since for aa and φ\varphi they already coincide at τ=0.1\tau=0.1: the slopes differ by 0.6% and 1.9%), after that they coincide on the drawing and the difference lives only in the digits: watch the number of agreeing significant digits rise and then fall.

误差下限由谁决定:Newton 迭代的停止准则

What sets the error floor: the Newton stopping criterion

两个 JhJ_h 都不是由精确离散解算出的:Newton 迭代在修正量不超过 10−1310^{-13} 时停止,最后一个修正量并不加上去。这个容差会不会就是误差下限?量一量。默认设计下基准求解的修正量依次是 2.7×10−22.7\times10^{-2}、3.3×10−43.3\times10^{-4}、4.6×10−84.6\times10^{-8}、8.6×10−168.6\times10^{-16}:二次收敛一步就越过了容差,返回的状态已经准确到舍入水平。所以默认容差 10−1310^{-13} 并不决定误差下限,舍入才决定(左支贴着舍入线,见上)。

Neither value of JhJ_h comes from the exact discrete solution: Newton stops when the correction is at most 10−1310^{-13}, and the last correction is not added. Is that tolerance the error floor? Measure it. At the defaults the corrections of the base solve are 2.7×10−22.7\times10^{-2}, 3.3×10−43.3\times10^{-4}, 4.6×10−84.6\times10^{-8}, 8.6×10−168.6\times10^{-16}: quadratic convergence jumps past the tolerance in one step, and the state returned is already accurate to rounding. So the default tolerance 10−1310^{-13} does not set the error floor; rounding does (the left branch follows the rounding line, see above).

放宽容差,情形就变了(图 72,分量 aa)。容差 10−410^{-4} 时只加上两个修正量(第三个 4.6×10−84.6\times10^{-8} 已低于容差),τ=10−3\tau=10^{-3} 到 10−710^{-7} 之间误差停在 6.07×10−76.07\times10^{-7} 附近(相对偏差小于 0.010.01),不再随 τ\tau 变化。原因是:只要两次求解的迭代步数相同,只迭代 mm 步的 Newton 迭代值 𝐔(m)(D)\mathbf U^{(m)}(D)(这里 mm 是迭代步数;第 5 节记作 𝐔k\mathbf U^k)本身就是 DD 的光滑函数,差商算出的是它的导数,偏差是一个固定的量,而不是被 1/τ1/\tau 放大的噪声。这里 m=2m=2:沿 Newton 迭代逐步求导,wT𝐔(2)w^T\mathbf U^{(2)} 的导数与 ∂aJh\partial_aJ_h 相差的正是这个数。容差 10−210^{-2} 时只加上一个修正量(第二个 3.3×10−43.3\times10^{-4} 已低于容差),平台落在 m=1m=1 的偏差 2.43×10−32.43\times10^{-3} 上(τ=10−2\tau=10^{-2} 到 10−810^{-8} 之间相对偏差小于 0.010.01)。容差 10−810^{-8} 和默认的 10−1310^{-13} 一样让三个修正量通过:wT𝐔(3)w^T\mathbf U^{(3)} 的导数只差 10−1210^{-12},状态已收敛到舍入水平,曲线就是默认设置的 V 形。

Loosen the tolerance and the picture changes (Figure 72, component aa). With the tolerance 10−410^{-4} only two corrections are added (the third, 4.6×10−84.6\times10^{-8}, is below the tolerance), and from τ=10−3\tau=10^{-3} to 10−710^{-7} the error stays near 6.07×10−76.07\times10^{-7} (relative deviation below 0.010.01), no longer depending on τ\tau. The reason: as long as both solves take the same number of steps, the Newton iterate 𝐔(m)(D)\mathbf U^{(m)}(D) after mm steps (mm counts steps here; Section 5 writes 𝐔k\mathbf U^k) is itself a smooth function of DD; the quotient computes its derivative, and the deviation is a fixed bias, not noise amplified by 1/τ1/\tau. Here m=2m=2: differentiating along the Newton iteration, the derivative of wT𝐔(2)w^T\mathbf U^{(2)} differs from ∂aJh\partial_aJ_h by exactly this number. With the tolerance 10−210^{-2} only one correction is added (the second, 3.3×10−43.3\times10^{-4}, is below the tolerance), and the plateau sits at the bias 2.43×10−32.43\times10^{-3} of m=1m=1 (relative deviation below 0.010.01 from τ=10−2\tau=10^{-2} to 10−810^{-8}). The tolerance 10−810^{-8} lets three corrections through, like the default 10−1310^{-13}: the derivative of wT𝐔(3)w^T\mathbf U^{(3)} differs by less than 10−1210^{-12}, the state is converged to rounding, and the curve is the V of the default.

热启动(以扰动前的解为初值)加一个绝对容差最危险:第一个修正量约为 τ∣vk∣\tau|v_k|,它一旦小于容差,求解器就原样返回初值,两个 JhJ_h 完全相等,差商为 0。容差 10−810^{-8} 时 τ≤10−8\tau\le10^{-8} 的点全是这样,误差就是梯度本身。

The most dangerous combination is a warm start (from the solution before the perturbation) with an absolute tolerance: the first correction is about τ∣vk∣\tau|v_k|, and once it is below the tolerance the solver returns its initial value unchanged, the two values of JhJ_h are identical and the quotient is 0. With the tolerance 10−810^{-8} this happens at every τ≤10−8\tau\le10^{-8}: the error is the gradient itself.

图 72 · 停止准则改变误差下限(分量 a,默认设计,N=8,无限制器线性,中心差分)。默认容差 10^(-13)(方块):V 形,噪声来自舍入;容差 10^(-4)(圈):与 τ 无关的平台,即 w^TU^((2)) 的导数与 ∂_aJ_h 之差;容差 10^(-2)(点):更高的平台,m=1 的偏差;热启动加容差 10^(-8)(虚线):小 τ 时求解器不动,差商为 0,误差等于 |D-bar_a|=0.1781。10-12​10-10​10-8​10-6​10-4​10-2​110-12​10-11​10-10​10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​步长 τ|FDc​ − 伴随梯度|冷启动,容差 10-13​(默认)冷启动,容差 10-4​冷启动,容差 10-2​热启动,容差 10-8​
图 72 · 停止准则改变误差下限(分量 aa,默认设计,N=8N=8,无限制器线性,中心差分)。默认容差 10−1310^{-13}(方块):V 形,噪声来自舍入;容差 10−410^{-4}(圈):与 τ\tau 无关的平台,即 wT𝐔(2)w^T\mathbf U^{(2)} 的导数与 ∂aJh\partial_aJ_h 之差;容差 10−210^{-2}(点):更高的平台,m=1m=1 的偏差;热启动加容差 10−810^{-8}(虚线):小 τ\tau 时求解器不动,差商为 0,误差等于 ∣Dˉa∣=0.1781|\bar D_a|=0.1781。
Figure 72 · The stopping criterion moves the error floor (component a, default design, N=8, unlimited linear, central differences). Default tolerance 10^(-13) (squares): the V, with rounding as the noise; tolerance 10^(-4) (rings): a plateau independent of τ, the bias of the derivative of w^TU^((2)); tolerance 10^(-2) (dots): a higher plateau, the bias of m=1; warm start with the tolerance 10^(-8) (dashed): for small τ the solver does not move, the quotient is 0 and the error equals |D-bar_a|=0.1781.10-12​10-10​10-8​10-6​10-4​10-2​110-12​10-11​10-10​10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​step τ|FDc​ − adjoint gradient|cold start, tolerance 10-13​ (default)cold start, tolerance 10-4​cold start, tolerance 10-2​warm start, tolerance 10-8​
Figure 72 · The stopping criterion moves the error floor (component aa, default design, N=8N=8, unlimited linear, central differences). Default tolerance 10−1310^{-13} (squares): the V, with rounding as the noise; tolerance 10−410^{-4} (rings): a plateau independent of τ\tau, the bias of the derivative of wT𝐔(2)w^T\mathbf U^{(2)}; tolerance 10−210^{-2} (dots): a higher plateau, the bias of m=1m=1; warm start with the tolerance 10−810^{-8} (dashed): for small τ\tau the solver does not move, the quotient is 0 and the error equals ∣Dˉa∣=0.1781|\bar D_a|=0.1781.

差分验证的四个陷阱:(1)不重新求解,差商是 JD=0J_D=0;(2)容差太松,差商趋向只迭代 mm 步的迭代值的导数,而不是 JhJ_h 的导数,误差停在一个与 τ\tau 无关的平台上;(3)热启动加绝对容差,小 τ\tau 时求解器不动,差商为 0;(4)热启动只走一步时,𝐔(1)=𝐔−A−1R(𝐔,D±τek)\mathbf U^{(1)}=\mathbf U-A^{-1}R(\mathbf U,D\pm\tau e_k) 的差商(当 AA 与 DkD_k 无关时)就是把 RDekR_De_k 换成它的中心差分近似 [R(𝐔,D+τek)−R(𝐔,D−τek)]/(2τ)[R(\mathbf U,D+\tau e_k)-R(\mathbf U,D-\tau e_k)]/(2\tau) 后的切线结果。对 aa(RR 是 aa 的二次函数,AA 与 aa 无关),它就是切线结果本身(τ=10−4\tau=10^{-4}、容差 10−810^{-8} 时与 wTvaw^Tv_a 只差不到 10−1110^{-11});对 φ\varphi 差 1.8×10−81.8\times10^{-8};对 ν\nu 连 AA 都变了(差 6.7×10−86.7\times10^{-8})。这时差分已不独立,Jacobian 里的错误会被它原样复制。可靠的做法:每个扰动点冷启动、收敛到舍入水平、扫描多个 τ\tau。另外 ν\nu 的步长必须小于 ν\nu 本身。

Four traps of the finite-difference check: (1) without a re-solve the quotient is JD=0J_D=0; (2) with a loose tolerance the quotient tends to the derivative of the iterate after mm Newton steps, not to the derivative of JhJ_h, and the error stays on a plateau independent of τ\tau; (3) with a warm start and an absolute tolerance the solver does not move for small τ\tau and the quotient is 0; (4) when a warm start takes a single step, the quotient of 𝐔(1)=𝐔−A−1R(𝐔,D±τek)\mathbf U^{(1)}=\mathbf U-A^{-1}R(\mathbf U,D\pm\tau e_k) is (when AA does not depend on DkD_k) the tangent result with RDekR_De_k replaced by its central difference [R(𝐔,D+τek)−R(𝐔,D−τek)]/(2τ)[R(\mathbf U,D+\tau e_k)-R(\mathbf U,D-\tau e_k)]/(2\tau). For aa (RR is quadratic in aa and AA does not depend on aa) that is the tangent result itself (at τ=10−4\tau=10^{-4} and the tolerance 10−810^{-8} it differs from wTvaw^Tv_a by less than 10−1110^{-11}); for φ\varphi the difference is 1.8×10−81.8\times10^{-8}; for ν\nu even AA changes (difference 6.7×10−86.7\times10^{-8}). Then the difference is no longer independent and copies any error of the Jacobian. The safe recipe: a cold start at every perturbed design, convergence to rounding, a scan over many τ\tau. And the step in ν\nu must be smaller than ν\nu itself.

最佳步长也随网格变化

The best step also changes with the mesh

在一个网格上选好的步长换一个网格未必还合适。光滑限制器的 ν\nu 分量(默认设计,完整重新求解的中心差分):N=8N=8 时 τ=10−5\tau=10^{-5} 就够(误差 2.8×10−92.8\times10^{-9}),可是 N=64N=64 到 512512 时 τ=10−5\tau=10^{-5} 的误差是 1.5×10−81.5\times10^{-8} 到 5.8×10−85.8\times10^{-8},超过 10−810^{-8};τ=10−6\tau=10^{-6} 时这四个网格的误差都小于 10−810^{-8}。原因是 τ2∣∂ν3Jh∣/6\tau^2|\partial_\nu^3J_h|/6:光滑限制器在 ν\nu 方向上的三阶导数随网格变大。所以扫描要在每个网格上重做;独立的 Python 程序自己的梯度检验用的就是 τ=10−5\tau=10^{-5},在这四个网格的 ν\nu 轴上碰到了同样的截断误差(第 15 节)。

A step chosen on one mesh may not suit another. The ν\nu-component of the smooth limiter (default design, central differences of full re-solves): at N=8N=8 τ=10−5\tau=10^{-5} is enough (error 2.8×10−92.8\times10^{-9}), but at N=64N=64 to 512512 the error at τ=10−5\tau=10^{-5} is 1.5×10−81.5\times10^{-8} to 5.8×10−85.8\times10^{-8}, above 10−810^{-8}; at τ=10−6\tau=10^{-6} the error on these four meshes is below 10−810^{-8}. The reason is τ2∣∂ν3Jh∣/6\tau^2|\partial_\nu^3J_h|/6: the third derivative of the smooth limiter in the ν\nu direction grows on these meshes. So the scan has to be repeated on every mesh; the independent Python program's own gradient check uses τ=10−5\tau=10^{-5} and meets the same truncation error on the ν\nu axis of these four meshes (Section 15).

NNNNτ=10−5\tau=10^{-5} 的误差error at τ=10−5\tau=10^{-5}τ=10−6\tau=10^{-6} 的误差error at τ=10−6\tau=10^{-6}
82.8e−91.9e−10
641.5e−83.4e−10
1285.3e−84.0e−10
2565.8e−84.4e−10
5122.6e−82.6e−10
10248.4e−92.9e−10

差分能抓住的两类错误

Two kinds of error that a difference catches

伴随梯度是 Dˉ=RDTψ\bar D=R_D^T\psi,它的每一项都来自 RDR_D 的某一行。格点格式里 RDR_D 有两部分:内部行 1≤j≤N−11\le j\le N-1 来自精确源项 Qf(D)Q_f(D) 和通量对 ν\nu 的显式依赖 −(UR−UL)/df-(U_R-U_L)/d_f;两个约束行 R0=U0−uin(D)R_0=U_0-u_{\rm in}(D)、RN=UN−uout(D)R_N=U_N-u_{\rm out}(D) 则带着边界数据对设计的导数 −duin/dDk-\mathrm du_{\rm in}/\mathrm dD_k、−duout/dDk-\mathrm du_{\rm out}/\mathrm dD_k,乘上的是边界乘子 ψ0\psi_0、ψN\psi_N。这两部分各漏掉一个,会得到什么?下表(无限制器线性,默认设计,N=8N=8):漏掉通量对 ν\nu 的显式导数,只有 ν\nu 分量变,伴随给出 2.1801072.180107,而差分给出 0.0039090.003909(正确的伴随值是 0.0039090.003909);把边界数据当成常数(两个约束行不带 du/dD\mathrm du/\mathrm dD),ν\nu 分量不变,aa、φ\varphi 分量变成 0.4576640.457664、2.1176022.117602,差分给出 −0.178061-0.178061、0.4199040.419904。两个错误都远大于差分误差,一眼就能看出。注意第二个:边界乘子 ψ0=−1.4061\psi_0=-1.4061、ψN=−0.0870\psi_N=-0.0870 不小,漏掉它们的贡献 ψ0(RD)0k+ψN(RD)Nk\psi_0(R_D)_{0k}+\psi_N(R_D)_{Nk} 对 aa 分量是 −0.6357-0.6357,对 φ\varphi 分量是 −1.6977-1.6977。

The adjoint gradient is Dˉ=RDTψ\bar D=R_D^T\psi, and each term of it comes from a row of RDR_D. On the node-centred page RDR_D has two parts: the interior rows 1≤j≤N−11\le j\le N-1 come from the exact source Qf(D)Q_f(D) and the explicit dependence of the flux on ν\nu, −(UR−UL)/df-(U_R-U_L)/d_f; the two constraint rows R0=U0−uin(D)R_0=U_0-u_{\rm in}(D) and RN=UN−uout(D)R_N=U_N-u_{\rm out}(D) carry the derivatives of the boundary data, −duin/dDk-\mathrm du_{\rm in}/\mathrm dD_k and −duout/dDk-\mathrm du_{\rm out}/\mathrm dD_k, multiplied by the boundary multipliers ψ0\psi_0 and ψN\psi_N. Leave out one of the two parts: what happens? The table below (unlimited linear, default design, N=8N=8): without the explicit ν\nu-derivative of the flux only the ν\nu-component changes, the adjoint gives 2.1801072.180107 and the difference 0.0039090.003909 (the correct adjoint value is 0.0039090.003909); with the boundary data treated as constants (the two constraint rows without du/dD\mathrm du/\mathrm dD) the ν\nu-component stays and the aa and φ\varphi components become 0.4576640.457664 and 2.1176022.117602, where the difference gives −0.178061-0.178061 and 0.4199040.419904. Both errors are far larger than any difference error, visible at a glance. Note the second: the boundary multipliers ψ0=−1.4061\psi_0=-1.4061 and ψN=−0.0870\psi_N=-0.0870 are not small, and the contribution that is lost, ψ0(RD)0k+ψN(RD)Nk\psi_0(R_D)_{0k}+\psi_N(R_D)_{Nk}, is −0.6357-0.6357 for the aa-component and −1.6977-1.6977 for the φ\varphi-component.

分量Component伴随梯度(正确)Adjoint gradient (correct)最佳中心差分Best central difference漏掉通量的 ν\nu 项Without the ν\nu term of the flux边界数据当常数Boundary data as constants
aa−0.178061−0.178061−0.1780610.457664
φ\varphi0.4199040.4199040.4199042.117602
ν\nu0.0039090.0039092.1801070.003909

选一个错误,看差分怎样揭穿它(实验里的“错误”是对 RDR_D 的列做的有意改动,伴随求解本身不变):

Pick a planted error and watch the difference expose it (the "errors" of the lab are deliberate changes to the columns of RDR_D; the adjoint solve itself is unchanged):

差分能做什么、不能做什么

What finite differences can and cannot do

  • 能:只用原始求解器就检验整条链——前向语句、反向语句、RDR_D(包括两个约束行)、转置和线性求解。上面两个错误都会被抓住。Can: check the whole chain with the primal solver only: tangent statements, reverse statements, RDR_D (the constraint rows included), the transpose and the linear solves. Both errors above are caught.
  • 不能:给出超过约 10 位的数字,而且只有扫描之后才知道哪个 τ\tau 可信;最佳 τ\tau 随分量、网格和重构变化。Cannot: deliver more than about 10 digits, and only a scan tells which τ\tau to trust; the best τ\tau changes with the component, the mesh and the reconstruction.
  • 不划算:每个分量 2 次非线性求解;伴随 1 次线性求解给出全部分量。Not cheap: 2 nonlinear solves per component; the adjoint gives all components with one linear solve.
  • 不回答离散误差的问题:差分与伴随都是 JhJ_h 的导数,它们离精确梯度多远是第 15、16 节的事。第 14 节的复数步长去掉了 V 形的舍入支。Does not answer the question of discretisation error: the difference and the adjoint are both derivatives of JhJ_h; how far they are from the exact gradient is the business of Sections 15 and 16. The complex step of Section 14 removes the rounding branch of the V.
第 14 节Section 14

复数步长验证:没有相减的差商

Complex-step check: a quotient without subtraction

本节实验:先算一算,在双精度里 a+10−30a+10^{-30} 等于多少?那么 τ=10−30\tau=10^{-30} 时第 13 节的中心差分给出什么?复数步长 Im⁡ Jh(D+iτek)/τ\operatorname{Im}\,J_h(D+i\tau e_k)/\tau 又给出什么?读完本节,用复数步长实验验证。

Experiment: work it out first: what is a+10−30a+10^{-30} in double precision? Then what does the central difference of Section 13 return at τ=10−30\tau=10^{-30}? And what does the complex step Im⁡ Jh(D+iτek)/τ\operatorname{Im}\,J_h(D+i\tau e_k)/\tau return? After the section, check with the complex-step lab.

第 13 节的差分受步长两头夹击:τ\tau 大时截断误差大;τ\tau 小时两个几乎相等的 JhJ_h 相减,舍入被 1/τ1/\tau 放大。双精度里 0.2+10−300.2+10^{-30} 就等于 0.20.2 本身,所以 τ=10−30\tau=10^{-30} 的差分是 0/(2τ)=00/(2\tau)=0。复数步长去掉了相减这一步。

The differences of Section 13 are squeezed from both ends of the step: at large τ\tau the truncation error is large; at small τ\tau two nearly equal values of JhJ_h are subtracted and the rounding is amplified by 1/τ1/\tau. In double precision 0.2+10−300.2+10^{-30} is 0.20.2 itself, so the difference at τ=10−30\tau=10^{-30} is 0/(2τ)=00/(2\tau)=0. The complex step removes the subtraction.

虚数方向上的一步

A step in the imaginary direction

设 JhJ_h 作为 DkD_k 的函数可以解析延拓到复平面(下一小节说明为什么可以)。把实的步长换成虚的 iτi\tau,在 DD 处展开:

Suppose JhJ_h, as a function of DkD_k, extends analytically into the complex plane (the next subsection says why it does). Replace the real step by the imaginary step iτi\tau and expand about DD:

Jh(D+iτek)=Jh+iτ ∂kJh−τ22 ∂k2Jh−i τ36 ∂k3Jh+O(τ4).J_h(D+i\tau e_k)=J_h+i\tau\,\partial_kJ_h-\frac{\tau^2}2\,\partial_k^2J_h-i\,\frac{\tau^3}6\,\partial_k^3J_h+O(\tau^4).

虚部与实部分开:

Separate the imaginary and the real parts:

CSτ=Im⁡ Jh(D+iτek)τ=∂kJh−τ26 ∂k3Jh+O(τ4),Re⁡ Jh(D+iτek)=Jh−τ22 ∂k2Jh+O(τ4).\mathrm{CS}_\tau=\frac{\operatorname{Im}\,J_h(D+i\tau e_k)}{\tau}=\partial_kJ_h-\frac{\tau^2}6\,\partial_k^3J_h+O(\tau^4),\qquad \operatorname{Re}\,J_h(D+i\tau e_k)=J_h-\frac{\tau^2}2\,\partial_k^2J_h+O(\tau^4).

导数直接从虚部读出,不需要两个相近的数相减,舍入不再被 1/τ1/\tau 放大。函数里含有求解器时,这个舍入就是复数求解的舍入,是 εmach∑i∣wivk,i∣\varepsilon_{\rm mach}\sum_i|w_iv_{k,i}| 的若干倍(按下表九个序列的平台计,是 1 到 60 倍,无限制器线性和光滑限制器的 ν\nu 分量最大):这里 ∑i∣wivk,i∣\sum_i|w_iv_{k,i}| 在 0.14 到 1.31 之间;它不是 εmach∣∂kJh∣\varepsilon_{\rm mach}|\partial_kJ_h|:无限制器线性的 ∣∂νJh∣|\partial_\nu J_h| 只有 0.0039,却是由大得多的项相加而成的(∑i∣wivν,i∣=0.147\sum_i|w_iv_{\nu,i}|=0.147)。后面表中复数步长与伴随、切线梯度之差不超过 10−1410^{-14}。截断误差 −τ2∂k3Jh/6-\tau^2\partial_k^3J_h/6 与中心差分的大小相同、符号相反。τ=10−30\tau=10^{-30} 时,无限制器线性的三个分量的截断误差都不超过 6.6×10−606.6\times10^{-60},完全看不见。图 73 用一个看得见的 τ\tau 画出这一步。

The derivative is read off the imaginary part directly; nothing nearly equal is subtracted, so the rounding is no longer amplified by 1/τ1/\tau. When the function contains a solver, the rounding is that of the complex solve, a multiple of εmach∑i∣wivk,i∣\varepsilon_{\rm mach}\sum_i|w_iv_{k,i}| (1 to 60 on the nine series of the table below, largest for the ν\nu components of unlimited linear and of the smooth limiter): here ∑i∣wivk,i∣\sum_i|w_iv_{k,i}| lies between 0.14 and 1.31; it is not εmach∣∂kJh∣\varepsilon_{\rm mach}|\partial_kJ_h|: for unlimited linear ∣∂νJh∣|\partial_\nu J_h| is only 0.0039, a sum of much larger terms (∑i∣wivν,i∣=0.147\sum_i|w_iv_{\nu,i}|=0.147). In the table below the complex step differs from the adjoint and the tangent gradients by at most 10−1410^{-14}. The truncation error −τ2∂k3Jh/6-\tau^2\partial_k^3J_h/6 has the size of the central difference's, with the opposite sign. At τ=10−30\tau=10^{-30} it is at most 6.6×10−606.6\times10^{-60} for the three components of the unlimited linear scheme: invisible. Figure 73 draws the step with a visible τ\tau.

图 73 · 复平面上的一步(分量 a,默认设计,无限制器线性;为了看得见取 τ=0.05)。左:设计 a 在实轴上,a+iτ 在它正上方。右:求解复数残差得到复数状态,目标 J_h(D+iτ e_a) 几乎正好落在 J_h 的正下方:虚部 -8.903 × 10^(-3) ≈ τ ∂_aJ_h(∂_aJ_h<0,所以向下),实部只偏了 -2.5 × 10^(-5) ≈ -τ^22∂_a^2J_h。ReIma = 0.200a + iττ = 0.05输入:设计 a求解ReImJh​ = 1.46394Jh​(D + iτea​)Im = −0.00890输出:目标 Jh​Im Jh​ / τ = −0.178063;伴随梯度 = −0.178061
图 73 · 复平面上的一步(分量 aa,默认设计,无限制器线性;为了看得见取 τ=0.05\tau=0.05)。左:设计 aa 在实轴上,a+iτa+i\tau 在它正上方。右:求解复数残差得到复数状态,目标 Jh(D+iτea)J_h(D+i\tau e_a) 几乎正好落在 JhJ_h 的正下方:虚部 −8.903×10−3≈τ ∂aJh-8.903\times10^{-3}\approx\tau\,\partial_aJ_h(∂aJh<0\partial_aJ_h<0,所以向下),实部只偏了 −2.5×10−5≈−τ22∂a2Jh-2.5\times10^{-5}\approx-\tfrac{\tau^2}2\partial_a^2J_h。
Figure 73 · One step in the complex plane (component a, default design, unlimited linear; τ=0.05 so that it can be seen). Left: the design a on the real axis and a+iτ straight above it. Right: solving the complex residual gives a complex state, and the objective J_h(D+iτ e_a) lands almost straight below J_h: the imaginary part -8.903 × 10^(-3) ≈ τ ∂_aJ_h (negative, since ∂_aJ_h<0), while the real part moved only by -2.5 × 10^(-5) ≈ -τ^22∂_a^2J_h.ReIma = 0.200a + iττ = 0.05input: the design asolveReImJh​ = 1.46394Jh​(D + iτea​)Im = −0.00890output: the objective Jh​Im Jh​ / τ = −0.178063; adjoint gradient = −0.178061
Figure 73 · One step in the complex plane (component aa, default design, unlimited linear; τ=0.05\tau=0.05 so that it can be seen). Left: the design aa on the real axis and a+iτa+i\tau straight above it. Right: solving the complex residual gives a complex state, and the objective Jh(D+iτea)J_h(D+i\tau e_a) lands almost straight below JhJ_h: the imaginary part −8.903×10−3≈τ ∂aJh-8.903\times10^{-3}\approx\tau\,\partial_aJ_h (negative, since ∂aJh<0\partial_aJ_h<0), while the real part moved only by −2.5×10−5≈−τ22∂a2Jh-2.5\times10^{-5}\approx-\tfrac{\tau^2}2\partial_a^2J_h.

对代码的要求:只用解析运算

What the code must be: analytic operations only

复数步长要求程序的每一步都是某个解析函数在实轴上的限制。加、减、乘、除和 sin⁡\sin、cos⁡\cos 都是;绝对值、max⁡\max、min⁡\min、按符号分支的 if 都不是。第 5 节的残差只用了加减乘除,设计里的 sin⁡\sin、cos⁡\cos 通过 u∗u^*、q∗q^* 和边界数据 uin(D)u_{\rm in}(D)、uout(D)u_{\rm out}(D) 进入(两个约束行 R0=U0−uin(D)R_0=U_0-u_{\rm in}(D)、RN=UN−uout(D)R_N=U_N-u_{\rm out}(D) 对复数设计照样成立):Rusanov 速度是常数 α=2\alpha=2,没有 ∣u∣|u|,三种斜率是 00、(l+r)/2(l+r)/2 和光滑限制器 lr(l+r)/(l2+r2+ϵ2)lr(l+r)/(l^2+r^2+\epsilon^2)。光滑限制器的分母在实轴上不小于 ϵ2>0\epsilon^2>0,所以它在每个实状态附近都是解析的,没有开关:三种重构都可以做复数步长。两个边界节点上的单侧斜率是线性的,不引入开关。AA 可逆时,由隐函数定理,离散解随设计解析地变化,JhJ_h 也就可以解析延拓。minmod 之类的限制器在开关处不可导,复数步长会默默地跟着实部选中的分支走。

The complex step needs every operation of the program to be the restriction of an analytic function to the real axis. Addition, subtraction, multiplication, division, sin⁡\sin and cos⁡\cos are; an absolute value, max⁡\max, min⁡\min and an if on a sign are not. The residual of Section 5 uses only the four operations, and the sin⁡\sin and cos⁡\cos of the design enter through u∗u^*, q∗q^* and the boundary data uin(D)u_{\rm in}(D), uout(D)u_{\rm out}(D) (the two constraint rows R0=U0−uin(D)R_0=U_0-u_{\rm in}(D) and RN=UN−uout(D)R_N=U_N-u_{\rm out}(D) hold for a complex design as they stand): the Rusanov speed is the constant α=2\alpha=2, there is no ∣u∣|u|, and the three slopes are 00, (l+r)/2(l+r)/2 and the smooth limiter lr(l+r)/(l2+r2+ϵ2)lr(l+r)/(l^2+r^2+\epsilon^2). The denominator of the smooth limiter is at least ϵ2>0\epsilon^2>0 on the real axis, so it is analytic near every real state and has no switch: all three reconstructions can be complex-stepped. The one-sided slopes at the two boundary nodes are linear and introduce no switch. Where AA is invertible, the implicit function theorem makes the discrete solution an analytic function of the design, and with it JhJ_h. A limiter such as minmod is not differentiable at its switch, and the complex step would silently follow the branch the real parts select.

model.js 的 residualComplex 就是第 5 节的残差代码,只把算术换成复数:实部和虚部各存一个数组,语句一条不改;sin⁡(x+iy)=sin⁡ x cosh⁡ y+i cos⁡ x sinh⁡ y\sin(x+iy)=\sin\,x\,\cosh\,y+i\,\cos\,x\,\sinh\,y,cos⁡(x+iy)=cos⁡ x cosh⁡ y−i sin⁡ x sinh⁡ y\cos(x+iy)=\cos\,x\,\cosh\,y-i\,\sin\,x\,\sinh\,y。其中没有一行是手工求导的,所以它是对第 8 节前向语句的独立检验。

The function residualComplex of model.js is the residual code of Section 5 with the arithmetic replaced: the real and the imaginary parts are two arrays, and not one statement changes; sin⁡(x+iy)=sin⁡ x cosh⁡ y+i cos⁡ x sinh⁡ y\sin(x+iy)=\sin\,x\,\cosh\,y+i\,\cos\,x\,\sinh\,y and cos⁡(x+iy)=cos⁡ x cosh⁡ y−i sin⁡ x sinh⁡ y\cos(x+iy)=\cos\,x\,\cosh\,y-i\,\sin\,x\,\sinh\,y. Not one line of it is differentiated by hand, which makes it an independent check of the tangent statements of Section 8.

复数版本必须用代数平方 z⋅zz\cdot z,不能用模的平方 ∣z∣2=z conj⁡(z)|z|^2=z\,\operatorname{conj}(z):共轭会把虚部消掉。目标 Jh=wT𝐔J_h=w^T\mathbf U 是线性的,所以 Im⁡ Jh=wTIm⁡ 𝐔\operatorname{Im}\,J_h=w^T\operatorname{Im}\,\mathbf U。

The complex version must use the algebraic square z⋅zz\cdot z, never the squared modulus ∣z∣2=z conj⁡(z)|z|^2=z\,\operatorname{conj}(z): the conjugate cancels the imaginary part. The objective Jh=wT𝐔J_h=w^T\mathbf U is linear, so Im⁡ Jh=wTIm⁡ 𝐔\operatorname{Im}\,J_h=w^T\operatorname{Im}\,\mathbf U.

状态也变成复数

The state becomes complex

设计 D+iτekD+i\tau e_k 让残差变成复数,离散解也随之是复数。在 τ=0\tau=0 处展开:

The design D+iτekD+i\tau e_k makes the residual complex, and with it the discrete solution. Expand about τ=0\tau=0:

𝐔(D+iτek)=𝐔(D)+iτ vk+O(τ2),vk=𝐔˙=∂𝐔∂Dk.\mathbf U(D+i\tau e_k)=\mathbf U(D)+i\tau\,v_k+O(\tau^2),\qquad v_k=\dot{\mathbf U}=\frac{\partial\mathbf U}{\partial D_k}.

虚部除以 τ\tau 就是第 10 节的切线解。函数里含有求解器时,复数步长本身就是一次复数求解:要解复数残差 R(𝐔,D+iτek)=0R(\mathbf U,D+i\tau e_k)=0。用 Newton 法,Jacobian 取实部的 AA:不动点 R(𝐔,D+iτek)=0R(\mathbf U,D+i\tau e_k)=0 与所用矩阵无关,舍去复 Jacobian 的 O(τ)O(\tau) 虚部不改变结果;但它使修正量的虚部改变 O(τ∥R∥)O(\tau\|R\|)(只有接近收敛时才可忽略),并使虚部晚一步收敛。把残差的虚部展开:

Its imaginary part over τ\tau is the tangent solution of Section 10. When the function contains a solver, the complex step is itself a complex solve: the complex residual R(𝐔,D+iτek)=0R(\mathbf U,D+i\tau e_k)=0 must be solved. Use Newton with the real Jacobian AA: the fixed point R(𝐔,D+iτek)=0R(\mathbf U,D+i\tau e_k)=0 does not depend on the matrix, so dropping the O(τ)O(\tau) imaginary part of the complex Jacobian leaves the result unchanged; it changes the imaginary part of a correction by O(τ∥R∥)O(\tau\|R\|) (negligible only near convergence) and makes the imaginary part lag one step. Expand the imaginary part of the residual:

Im⁡ R(𝐔+iτv, D+iτek)=τ (Av+RDek)+O(τ3).\operatorname{Im}\,R\bigl(\mathbf U+i\tau v,\ D+i\tau e_k\bigr)=\tau\,\bigl(Av+R_De_k\bigr)+O(\tau^3).

令它为零,正是第 10 节的切线方程 Av=−RDekAv=-R_De_k:虚部的一次 Newton 修正就是一次前向求解(乘以 τ\tau)。于是

Setting it to zero is exactly the tangent equation Av=−RDekAv=-R_De_k of Section 10: one Newton correction of the imaginary part is one tangent solve (times τ\tau). Hence

CSτ=Im⁡ Jh(D+iτek)τ=wTIm⁡ 𝐔τ=wTvk+O(τ2)=J˙+O(τ2).\mathrm{CS}_\tau=\frac{\operatorname{Im}\,J_h(D+i\tau e_k)}{\tau}=\frac{w^T\operatorname{Im}\,\mathbf U}{\tau}=w^Tv_k+O(\tau^2)=\dot J+O(\tau^2).

两个边界节点上这一步是精确的:约束行 R0=U0−uin(D)R_0=U_0-u_{\rm in}(D) 对 𝐔\mathbf U 的 Jacobian 行是单位行,所以虚部除以 τ\tau 在第一帧(初值 u∗(xj;D+iτek)u^*(x_j;D+i\tau e_k) 本身)就是 duin/dDk\mathrm du_{\rm in}/\mathrm dD_k,duout/dDk\mathrm du_{\rm out}/\mathrm dD_k,与切线解在这两个节点上的值相同(三个分量的最大偏差不超过 10−1510^{-15})。

At the two boundary nodes the step is exact: the Jacobian row of the constraint row R0=U0−uin(D)R_0=U_0-u_{\rm in}(D) is a unit row, so the imaginary part over τ\tau is duin/dDk\mathrm du_{\rm in}/\mathrm dD_k and duout/dDk\mathrm du_{\rm out}/\mathrm dD_k from the first frame on (the initial guess u∗(xj;D+iτek)u^*(x_j;D+i\tau e_k) itself), the values of the tangent solution at those two nodes (largest deviation over the three components at most 10−1510^{-15}).

下面的播放器从页面的初值 u∗(xj;D+iτek)u^*(x_j;D+i\tau e_k) 出发做复数 Newton 迭代(τ=10−30\tau=10^{-30}),每一步用当前实部的 Jacobian。τ=10−30\tau=10^{-30} 时实部与第 5 节的原始迭代一致到最后一位(Re⁡ R=R−τ22(⋯ )\operatorname{Re}\,R=R-\tfrac{\tau^2}2(\cdots);τ=10−30\tau=10^{-30} 时 τ2\tau^2 项约为 10−6010^{-60},远小于 O(1)O(1) 实部的最后一位):一阶和无限制器线性逐位相同;光滑限制器的复数除法与实数除法的舍入可以差最后一位,所以在某些网格和设计上它的个别迭代值相差几个最后一位(默认设计、N=8N=8 上三种重构都逐位相同)。虚部晚一步:Im⁡ 𝐔(m+1)/τ\operatorname{Im}\,\mathbf U^{(m+1)}/\tau 恰好是在实部迭代值 𝐔(m)\mathbf U^{(m)} 处求得的切线解(每一步都取整步时成立,默认设计下正是如此;差不超过 10−1410^{-14})。残差实部在 3 次修正后到达舍入水平,虚部在 4 次修正后(图 74)。

The player below runs the complex Newton iteration from the page's initial guess u∗(xj;D+iτek)u^*(x_j;D+i\tau e_k) (τ=10−30\tau=10^{-30}), with the Jacobian of the current real part at every step. At τ=10−30\tau=10^{-30} the real part is the primal iteration of Section 5 to the last bit (Re⁡ R=R−τ22(⋯ )\operatorname{Re}\,R=R-\tfrac{\tau^2}2(\cdots); at τ=10−30\tau=10^{-30} the τ2\tau^2 terms, about 10−6010^{-60}, are far below the last bit of the O(1)O(1) real parts): bit for bit for first order and unlimited linear; with the smooth limiter the complex division rounds differently from the real one in the last place, so on some meshes and designs some of its iterates differ by a few units in the last place (at the default design and N=8N=8 all three reconstructions are bit for bit). The imaginary part lags one step: Im⁡ 𝐔(m+1)/τ\operatorname{Im}\,\mathbf U^{(m+1)}/\tau is exactly the tangent solution at the real iterate 𝐔(m)\mathbf U^{(m)} (as long as every step is a full step, as at the defaults; to 10−1410^{-14} or better). The real residual reaches rounding after 3 corrections, the imaginary one after 4 (Figure 74).

图 74 · 复数 Newton 迭代的收敛(分量 a,τ=10^(-30),默认设计,无限制器线性)。方块:残差实部;点:残差虚部除以 τ;圈:w^TIm U^((m))/τ 与伴随梯度之差。实部二次收敛,3 次修正后到达舍入水平;虚部晚一步,4 次修正后到达;最后与伴随梯度之差不到 10^(-14)(舍入量级;下表给出收敛求解的值)。10-16​10-14​10-12​10-10​10-8​10-6​10-4​10-2​101234Newton 迭代 m范数|Re R(U(m)​)||Im R(U(m)​)| / τ|wT​ Im U(m)​/τ − 伴随梯度|
图 74 · 复数 Newton 迭代的收敛(分量 aa,τ=10−30\tau=10^{-30},默认设计,无限制器线性)。方块:残差实部;点:残差虚部除以 τ\tau;圈:wTIm⁡ 𝐔(m)/τw^T\operatorname{Im}\,\mathbf U^{(m)}/\tau 与伴随梯度之差。实部二次收敛,3 次修正后到达舍入水平;虚部晚一步,4 次修正后到达;最后与伴随梯度之差不到 10−1410^{-14}(舍入量级;下表给出收敛求解的值)。
Figure 74 · Convergence of the complex Newton iteration (component a, τ=10^(-30), default design, unlimited linear). Squares: the real part of the residual; dots: its imaginary part over τ; rings: w^TIm U^((m))/τ minus the adjoint gradient. The real part converges quadratically and reaches rounding after 3 corrections; the imaginary part lags one step and gets there after 4; at the end the difference from the adjoint gradient is below 10^(-14) (rounding level; the table below gives the value of the converged solve).10-16​10-14​10-12​10-10​10-8​10-6​10-4​10-2​101234Newton iteration mnorm|Re R(U(m)​)||Im R(U(m)​)| / τ|wT​ Im U(m)​/τ − adjoint gradient|
Figure 74 · Convergence of the complex Newton iteration (component aa, τ=10−30\tau=10^{-30}, default design, unlimited linear). Squares: the real part of the residual; dots: its imaginary part over τ\tau; rings: wTIm⁡ 𝐔(m)/τw^T\operatorname{Im}\,\mathbf U^{(m)}/\tau minus the adjoint gradient. The real part converges quadratically and reaches rounding after 3 corrections; the imaginary part lags one step and gets there after 4; at the end the difference from the adjoint gradient is below 10−1410^{-14} (rounding level; the table below gives the value of the converged solve).

图 75 把收敛后的虚部除以 τ\tau 与第 10 节的切线解画在一起:三个分量的最大差都不超过 10−1410^{-14}。表中是三种重构下 τ=10−30\tau=10^{-30} 的复数步长梯度,与伴随梯度、切线梯度相差都不超过 10−1410^{-14},而第 13 节的中心差分即使在最佳步长处,误差也有 10−1210^{-12} 到 10−910^{-9}。

Figure 75 draws the converged imaginary part over τ\tau over the tangent solution of Section 10: the largest differences for the three components are at most 10−1410^{-14}. The table lists the complex-step gradients at τ=10−30\tau=10^{-30} for the three reconstructions: they differ from the adjoint and the tangent gradients by at most 10−1410^{-14}, while the central difference of Section 13 gets only to 10−1210^{-12} to 10−910^{-9} at its best step.

图 75 · 状态虚部除以 τ 就是切线解(τ=10^(-30),默认设计,无限制器线性)。实线:第 10 节的切线解 v_a,v_φ,v_ν;圈:复数求解得到的 Im U/τ。两者重合到舍入水平,两个端点上也一样。−1−0.500.511.500.20.40.60.81xIm Uj​ / τ 与 vj​切线解 va​切线解 vφ​切线解 vν​
图 75 · 状态虚部除以 τ\tau 就是切线解(τ=10−30\tau=10^{-30},默认设计,无限制器线性)。实线:第 10 节的切线解 va,vφ,vνv_a,v_\varphi,v_\nu;圈:复数求解得到的 Im⁡ 𝐔/τ\operatorname{Im}\,\mathbf U/\tau。两者重合到舍入水平,两个端点上也一样。
Figure 75 · The imaginary part of the state over τ is the tangent solution (τ=10^(-30), default design, unlimited linear). Lines: the tangent solutions v_a,v_φ,v_ν of Section 10; rings: Im U/τ from the complex solve. They coincide to rounding, at the two end nodes too.−1−0.500.511.500.20.40.60.81xIm Uj​ / τ and vj​tangent solution va​tangent solution vφ​tangent solution vν​
Figure 75 · The imaginary part of the state over τ\tau is the tangent solution (τ=10−30\tau=10^{-30}, default design, unlimited linear). Lines: the tangent solutions va,vφ,vνv_a,v_\varphi,v_\nu of Section 10; rings: Im⁡ 𝐔/τ\operatorname{Im}\,\mathbf U/\tau from the complex solve. They coincide to rounding, at the two end nodes too.
重构Reconstruction分量ComponentCSτ\mathrm{CS}_\tau(τ=10−30\tau=10^{-30})CSτ\mathrm{CS}_\tau at τ=10−30\tau=10^{-30}与伴随之差Minus adjoint与切线之差Minus tangent中心差分最佳误差Best central FD
一阶first orderaa−1.1751762037654.4e−162.2e−165.1e−11
一阶first orderφ\varphi−0.2345937494003.9e−165.6e−171.2e−10
一阶first orderν\nu0.9925748669778.9e−166.7e−161.2e−11
无限制器线性unlimited linearaa−0.1780611531762.5e−167.5e−166.6e−12
无限制器线性unlimited linearφ\varphi0.4199038734756.7e−167.2e−168.5e−11
无限制器线性unlimited linearν\nu0.0039088428579.1e−168.8e−165.9e−11
光滑限制器smooth limiteraa−0.1882103301055.6e−162.8e−165.3e−12
光滑限制器smooth limiterφ\varphi0.5534678233953.3e−168.9e−162.7e−10
光滑限制器smooth limiterν\nu−0.3149999604843.7e−153.9e−151.9e−10

步长扫描:没有 V 形

The step scan: no V

把第 13 节的扫描延长到 τ=10−30\tau=10^{-30}(图 76)。τ\tau 大时复数步长与中心差分的误差大小相同、符号相反:τ=10−2\tau=10^{-2} 时 aa、φ\varphi 分量的比值是 −0.9986-0.9986、−1.0001-1.0001;τ=10−3\tau=10^{-3} 时是 −1.000-1.000、−1.000-1.000。τ≤10−7\tau\le10^{-7} 时,分量 aa(无限制器线性)的复数步长误差一直低于 3×10−153\times10^{-15}。三种重构的全部九个序列在 τ≤10−9\tau\le10^{-9} 的所有点都停在舍入水平(不超过 10−1410^{-14}),一直到 τ=10−30\tau=10^{-30}。中心差分则在 τ=10−4\tau=10^{-4} 到 10−610^{-6} 见底后又回升。τ\tau 很大时复数 Newton 迭代可能不收敛:τ=0.1\tau=0.1 时,无限制器线性的 ν\nu 分量、光滑限制器的 φ\varphi 分量和 ν\nu 分量不收敛,图里没有画这些点。

Extend the scan of Section 13 down to τ=10−30\tau=10^{-30} (Figure 76). At large τ\tau the complex step and the central difference have errors of the same size and opposite sign: at τ=10−2\tau=10^{-2} their ratio is −0.9986-0.9986 and −1.0001-1.0001 for aa and φ\varphi, at τ=10−3\tau=10^{-3} −1.000-1.000 and −1.000-1.000. For τ≤10−7\tau\le10^{-7} the complex-step error of component aa (unlimited linear) stays below 3×10−153\times10^{-15}. All nine series of the three reconstructions stay at rounding level at every point with τ≤10−9\tau\le10^{-9} (at most 10−1410^{-14}), down to τ=10−30\tau=10^{-30}. The central difference instead bottoms out at τ=10−4\tau=10^{-4} to 10−610^{-6} and rises again. At a very large τ\tau the complex Newton iteration may not converge: at τ=0.1\tau=0.1 for the ν\nu-component of unlimited linear, the φ\varphi-component of smooth limiter, the ν\nu-component of smooth limiter; those points are not drawn.

图 76 · 复数步长与中心差分的步长扫描(默认设计,N=8,无限制器线性)。方块:中心差分;实心点:复数步长,每个 τ 都是一次复数求解。复数步长在 τ 大时与中心差分重合(截断误差 τ^2|∂_k^3J_h|/6),之后停在舍入水平,一直到 10^(-30);没有 V 形。ν 分量在 τ=0.1 时复数 Newton 迭代不收敛,那一点没有画;中心差分要求 τ<ν。10-18​10-16​10-14​10-12​10-10​10-8​10-6​10-4​10-2​110-30​10-25​10-20​10-15​10-10​10-5​步长 τ|差商 − 伴随梯度|舍入线 εmach​|Jh​|/τ分量 a:∂Jh​/∂a = −0.178061中心差分 FDc​复数步长 CS10-18​10-16​10-14​10-12​10-10​10-8​10-6​10-4​10-2​110-30​10-25​10-20​10-15​10-10​10-5​步长 τ|差商 − 伴随梯度|舍入线 εmach​|Jh​|/τ分量 φ:∂Jh​/∂φ = 0.419904中心差分 FDc​复数步长 CS10-18​10-16​10-14​10-12​10-10​10-8​10-6​10-4​10-2​110-30​10-25​10-20​10-15​10-10​10-5​步长 τ|差商 − 伴随梯度|舍入线 εmach​|Jh​|/τ分量 ν:∂Jh​/∂ν = 0.003909中心差分 FDc​复数步长 CS
图 76 · 复数步长与中心差分的步长扫描(默认设计,N=8N=8,无限制器线性)。方块:中心差分;实心点:复数步长,每个 τ\tau 都是一次复数求解。复数步长在 τ\tau 大时与中心差分重合(截断误差 τ2∣∂k3Jh∣/6\tau^2|\partial_k^3J_h|/6),之后停在舍入水平,一直到 10−3010^{-30};没有 V 形。ν\nu 分量在 τ=0.1\tau=0.1 时复数 Newton 迭代不收敛,那一点没有画;中心差分要求 τ<ν\tau<\nu。
Figure 76 · Step scans of the complex step and the central difference (default design, N=8, unlimited linear). Squares: central differences; dots: the complex step, one complex solve per τ. At large τ the complex step coincides with the central difference (truncation τ^2|∂_k^3J_h|/6), then it stays at rounding level all the way down to 10^(-30): no V. For ν the complex Newton iteration does not converge at τ=0.1, so that point is not drawn; the central difference needs τ<ν.10-18​10-16​10-14​10-12​10-10​10-8​10-6​10-4​10-2​110-30​10-25​10-20​10-15​10-10​10-5​step τ|quotient − adjoint gradient|rounding εmach​|Jh​|/τcomponent a: ∂Jh​/∂a = −0.178061central FDc​complex step CS10-18​10-16​10-14​10-12​10-10​10-8​10-6​10-4​10-2​110-30​10-25​10-20​10-15​10-10​10-5​step τ|quotient − adjoint gradient|rounding εmach​|Jh​|/τcomponent φ: ∂Jh​/∂φ = 0.419904central FDc​complex step CS10-18​10-16​10-14​10-12​10-10​10-8​10-6​10-4​10-2​110-30​10-25​10-20​10-15​10-10​10-5​step τ|quotient − adjoint gradient|rounding εmach​|Jh​|/τcomponent ν: ∂Jh​/∂ν = 0.003909central FDc​complex step CS
Figure 76 · Step scans of the complex step and the central difference (default design, N=8N=8, unlimited linear). Squares: central differences; dots: the complex step, one complex solve per τ\tau. At large τ\tau the complex step coincides with the central difference (truncation τ2∣∂k3Jh∣/6\tau^2|\partial_k^3J_h|/6), then it stays at rounding level all the way down to 10−3010^{-30}: no V. For ν\nu the complex Newton iteration does not converge at τ=0.1\tau=0.1, so that point is not drawn; the central difference needs τ<ν\tau<\nu.

τ=10−8\tau=10^{-8} 附近:哪部分是截断,哪部分是舍入

Around τ=10−8\tau=10^{-8}: what is truncation and what is rounding

τ\tau 取 10−710^{-7} 到 10−810^{-8} 时,复数步长还剩一点截断误差,它藏在舍入误差里,双精度的数看不清。要看清,需要一个没有舍入的参照:把同一个复数求解用扩展精度重做(figs_e50.js:BigInt 定点数,小数部分 256 个二进制位;复数残差压到 10−6010^{-60} 以下,做法是用实 Jacobian 的双精度 LU 做迭代精化,残差用扩展精度算;检验用 mpmath 的 80 位十进制精度计算)。这样得到的 CSτ−∂kJh\mathrm{CS}_\tau-\partial_kJ_h 只剩截断误差(∂kJh\partial_kJ_h 取 τ=10−25\tau=10^{-25} 的复数步长,它的截断误差小于 10−4810^{-48})。

For τ\tau from 10−710^{-7} to 10−810^{-8} the complex step still holds a little truncation error, hidden in the rounding, so that the double-precision numbers cannot show it. To see it, take a reference without rounding: repeat the same complex solve in extended precision (figs_e50.js: BigInt fixed point with 256 fractional bits; the residual of the complex solve is brought below 10−6010^{-60} by iterative refinement, with the residual in extended precision and the corrections from the double-precision LU of the real Jacobian; the checks compare with mpmath at 80 digits). What remains of CSτ−∂kJh\mathrm{CS}_\tau-\partial_kJ_h is truncation only (∂kJh\partial_kJ_h is the complex step at τ=10−25\tau=10^{-25}, whose truncation error is below 10−4810^{-48}).

第一,扩展精度的误差就是 Taylor 项:τ=10−6\tau=10^{-6} 时它与 −τ2∂k3Jh/6-\tau^2\partial_k^3J_h/6 之比与 1 相差不超过 10−410^{-4},九个序列都是(三阶导数本身由第 13 节的伴随梯度差分得到,所以这也是对它的一次独立检验)。截断误差的公式没有问题,复数步长没有别的误差来源。

First, the error in extended precision is the Taylor term: at τ=10−6\tau=10^{-6} its ratio to −τ2∂k3Jh/6-\tau^2\partial_k^3J_h/6 differs from 1 by at most 10−410^{-4} for all nine series (the third derivative itself is differenced from adjoint gradients as in Section 13, so this also checks it independently). The formula for the truncation error is right, and the complex step has no other source of error.

第二,什么叫“还看得见截断误差”?这里取:扩展精度的误差大于这个序列在 τ≤10−12\tau\le10^{-12} 时双精度的最大误差的两倍。τ≤10−12\tau\le10^{-12} 时截断误差已小于 10−2310^{-23},剩下的全是舍入,这个最大误差就是该序列的舍入平台,九个序列的平台在 10−1610^{-16} 到 10−1410^{-14} 之间。按这个标准,τ=10−7\tau=10^{-7} 时有 7 个序列还看得见截断误差:一阶的 aa 分量、一阶的 φ\varphi 分量、一阶的 ν\nu 分量、无限制器线性的 φ\varphi 分量、无限制器线性的 ν\nu 分量、光滑限制器的 φ\varphi 分量、光滑限制器的 ν\nu 分量;τ=10−9\tau=10^{-9} 时有 0 个。τ=10−8\tau=10^{-8} 是过渡:九个序列里最大的截断项 τ2∣∂k3Jh∣/6\tau^2|\partial_k^3J_h|/6 是 6.0×10−156.0\times10^{-15}(光滑限制器的 φ\varphi 分量),与平台同量级。能不能看见取决于那一次的舍入,所以这一步不数个数;下表是 τ=10−8\tau=10^{-8} 的九个序列,最后一列是扩展精度的误差与平台之比。

Second, what does "still shows truncation" mean? Here: the error in extended precision is larger than twice the largest double-precision error of that series at τ≤10−12\tau\le10^{-12}. There the truncation error is below 10−2310^{-23} and everything left is rounding, so that largest error is the rounding plateau of the series; the nine plateaus lie between 10−1610^{-16} and 10−1410^{-14}. By this criterion 7 series still show truncation at τ=10−7\tau=10^{-7}: the aa-component of first order, the φ\varphi-component of first order, the ν\nu-component of first order, the φ\varphi-component of unlimited linear, the ν\nu-component of unlimited linear, the φ\varphi-component of smooth limiter, the ν\nu-component of smooth limiter; at τ=10−9\tau=10^{-9} the number is 0. τ=10−8\tau=10^{-8} is the transition: the largest truncation term τ2∣∂k3Jh∣/6\tau^2|\partial_k^3J_h|/6 of the nine series is 6.0×10−156.0\times10^{-15} (the φ\varphi-component of smooth limiter), about the size of the plateaus. Whether it can be seen depends on the rounding of that one run, so the page does not count series at this step; the table lists the nine series at τ=10−8\tau=10^{-8}, its last column being the error in extended precision over the plateau.

重构Reconstruction分量Component∂k3Jh\partial_k^3J_h∂k3Jh\partial_k^3J_hTaylor 项 −τ2∂k3Jh/6-\tau^2\partial_k^3J_h/6Taylor term −τ2∂k3Jh/6-\tau^2\partial_k^3J_h/6扩展精度Extended只舍入实部Re U rounded双精度Double舍入平台Plateau扩展精度 / 平台Extended / plateau
一阶first orderaa−3.32e05.54e−175.54e−175.93e−17−4.44e−168.88e−160.1
一阶first orderφ\varphi6.86e0−1.14e−16−1.14e−16−1.18e−16−9.16e−169.44e−160.1
一阶first orderν\nu−6.86e11.14e−151.14e−151.87e−152.44e−151.22e−150.9
无限制器线性unlimited linearaa5.19e−3−8.65e−20−8.65e−202.17e−174.72e−163.89e−160.0
无限制器线性unlimited linearφ\varphi−1.34e12.23e−162.23e−169.54e−17−9.99e−161.39e−150.2
无限制器线性unlimited linearν\nu−3.94e16.56e−166.56e−16−3.35e−16−9.82e−161.12e−150.6
光滑限制器smooth limiteraa−1.65e−22.75e−192.75e−195.87e−173.05e−168.33e−160.0
光滑限制器smooth limiterφ\varphi3.61e2−6.02e−15−6.02e−15−6.25e−15−4.55e−157.77e−167.8
光滑限制器smooth limiterν\nu1.69e2−2.82e−15−2.82e−15−1.27e−15−2.28e−154.16e−150.7

第三,差距由谁承担?双精度与扩展精度的差,在 τ≤10−8\tau\le10^{-8} 的所有点、所有序列上都不超过 10−1410^{-14},而且不随 τ\tau 变小:这就是舍入。扩展精度里,实部的 O(τ2)O(\tau^2) 偏移在 τ=10−8\tau=10^{-8} 时只有 εmachmax⁡j∣Uj∣\varepsilon_{\rm mach}\max_j|U_j| 的 0.01 到 5.26 倍,τ=10−9\tau=10^{-9} 时只有 1.9×10−41.9\times10^{-4} 到 5.3×10−25.3\times10^{-2} 倍:双精度的状态只能把它表示成 0、1 个或几个最后一位。它只是截断误差进入虚部的两条通道之一,另一条是残差显含的 τ3\tau^3 项;一阶和无限制器线性的 aa、ν\nu 分量只有实部偏移这一条通道,两者的 φ\varphi 分量里它只占 30% 和 22%。所以在它起主要作用的序列上,τ\tau 取这么小时截断误差的数值是量化的,不可靠。另做一个实验:从扩展精度的精确解出发,只把状态实部舍入到双精度,其余一切仍是扩展精度。复数步长就有了一个与 τ\tau 无关的下限(表中“只舍入实部”一列,τ=10−9\tau=10^{-9} 时九个序列在 1.2×10−171.2\times10^{-17} 到 1.7×10−151.7\times10^{-15} 之间),对 ν\nu 分量和光滑限制器的 φ\varphi 分量,这已是该序列舍入平台的相当一部分(比较表中的两列):导数是在一个只知道到双精度的状态上求的;平台的其余部分来自双精度下残差的计算和线性求解。图 77 画出其中三个序列。

Third, what carries the gap? The difference between double and extended precision is at most 10−1410^{-14} at every point with τ≤10−8\tau\le10^{-8} for every series, and it does not shrink with τ\tau: that is rounding. In extended precision the O(τ2)O(\tau^2) shift of the real part is only 0.01 to 5.26 times εmachmax⁡j∣Uj∣\varepsilon_{\rm mach}\max_j|U_j| at τ=10−8\tau=10^{-8}, and 1.9×10−41.9\times10^{-4} to 5.3×10−25.3\times10^{-2} times at τ=10−9\tau=10^{-9}: a double-precision state can represent it only as 0, 1 or a few units in the last place. It is one of two channels through which the truncation error enters the imaginary part, the other being the explicit τ3\tau^3 term of the residual; for the aa and ν\nu components of first order and unlimited linear it is the only channel, for the φ\varphi components of those two it carries only 30% and 22%. So for the series where it dominates, the numerical value of the truncation error at such small τ\tau is quantised and not reliable. One more experiment: start from the exact solution in extended precision, round only the real part of the state to double, and keep everything else in extended precision. The complex step then has a floor independent of τ\tau (the column "Re U rounded" of the table; at τ=10−9\tau=10^{-9} the nine series lie between 1.2×10−171.2\times10^{-17} and 1.7×10−151.7\times10^{-15}), for the ν\nu-components and the φ\varphi-component of the smooth limiter already a sizeable part of the rounding plateau of the series (compare the two columns of the table): the derivative is taken at a state that is known only to double precision; the rest of the plateau comes from evaluating the residual and solving the linear systems in double precision. Figure 77 draws three of the series.

图 77 · 扩展精度里的复数步长误差(默认设计,N=8)。上:光滑限制器的 φ 分量(τ=10^(-8) 处截断误差还高于舍入平台);中:无限制器线性的 ν 分量;下:无限制器线性的 a 分量(三阶导数很小,截断误差很快淹没在舍入里)。方块:扩展精度的误差,沿斜率 2 的 Taylor 线(实线)一直下降;圈(虚线):只把状态实部舍入到双精度;点:双精度例程的误差;点线:舍入平台。10-24​10-22​10-20​10-18​10-16​10-14​10-12​10-10​10-8​10-14​10-12​10-10​10-8​10-6​10-4​步长 τ|CS − D̄k​|舍入平台扩展精度(截断误差)只把状态实部舍入双精度分量 φ,光滑限制器10-24​10-22​10-20​10-18​10-16​10-14​10-12​10-10​10-8​10-14​10-12​10-10​10-8​10-6​10-4​步长 τ|CS − D̄k​|舍入平台扩展精度(截断误差)只把状态实部舍入双精度分量 ν,无限制器线性10-24​10-22​10-20​10-18​10-16​10-14​10-12​10-10​10-8​10-14​10-12​10-10​10-8​10-6​10-4​步长 τ|CS − D̄k​|舍入平台扩展精度(截断误差)只把状态实部舍入双精度分量 a,无限制器线性
图 77 · 扩展精度里的复数步长误差(默认设计,N=8N=8)。上:光滑限制器的 φ\varphi 分量(τ=10−8\tau=10^{-8} 处截断误差还高于舍入平台);中:无限制器线性的 ν\nu 分量;下:无限制器线性的 aa 分量(三阶导数很小,截断误差很快淹没在舍入里)。方块:扩展精度的误差,沿斜率 2 的 Taylor 线(实线)一直下降;圈(虚线):只把状态实部舍入到双精度;点:双精度例程的误差;点线:舍入平台。
Figure 77 · Errors of the complex step in extended precision (default design, N=8). Top: the φ-component of the smooth limiter (at τ=10^(-8) the truncation error is still above the rounding plateau); middle: the ν-component of unlimited linear; bottom: the a-component of unlimited linear (its third derivative is small and the truncation error sinks into the rounding early). Squares: the error in extended precision, falling along the Taylor line of slope 2; rings (dashed): only the real part of the state rounded to double; dots: the double-precision routine; dotted line: the rounding plateau.10-24​10-22​10-20​10-18​10-16​10-14​10-12​10-10​10-8​10-14​10-12​10-10​10-8​10-6​10-4​step τ|CS − D̄k​|rounding plateauextended precision (truncation)only the real part of the state roundeddouble precisioncomponent φ, smooth limiter10-24​10-22​10-20​10-18​10-16​10-14​10-12​10-10​10-8​10-14​10-12​10-10​10-8​10-6​10-4​step τ|CS − D̄k​|rounding plateauextended precision (truncation)only the real part of the state roundeddouble precisioncomponent ν, unlimited linear10-24​10-22​10-20​10-18​10-16​10-14​10-12​10-10​10-8​10-14​10-12​10-10​10-8​10-6​10-4​step τ|CS − D̄k​|rounding plateauextended precision (truncation)only the real part of the state roundeddouble precisioncomponent a, unlimited linear
Figure 77 · Errors of the complex step in extended precision (default design, N=8N=8). Top: the φ\varphi-component of the smooth limiter (at τ=10−8\tau=10^{-8} the truncation error is still above the rounding plateau); middle: the ν\nu-component of unlimited linear; bottom: the aa-component of unlimited linear (its third derivative is small and the truncation error sinks into the rounding early). Squares: the error in extended precision, falling along the Taylor line of slope 2; rings (dashed): only the real part of the state rounded to double; dots: the double-precision routine; dotted line: the rounding plateau.

自己改:选重构和分量,看扩展精度的误差怎样贴着 Taylor 线下降,双精度的点怎样停在平台上(扩展精度在浏览器里计算,只对 N≤32N\le32 的网格)。

Try it: pick the reconstruction and the component and watch the error in extended precision follow the Taylor line while the double-precision points stop at the plateau (the extended-precision computation runs in the browser, for meshes with N≤32N\le32 only).

用复数步长检验 Jacobian 的每一列

Every column of the Jacobians by the complex step

同一个复数程序还能给出 Jacobian 的列。给状态分量 jj 一个虚扰动:Im⁡ R(𝐔+iτej,D)/τ=Aej+O(τ2)\operatorname{Im}\,R(\mathbf U+i\tau e_j,D)/\tau=Ae_j+O(\tau^2),这就是 AA 的列 jj,没有用到任何前向语句;给设计虚扰动则得到 RDekR_De_k。默认设计下,所有列(AA 的 N+1N+1 列、RDR_D 的 3 列)与第 8 节前向语句算出的列的最大差:

The same complex program also gives the columns of the Jacobians. An imaginary perturbation of state component jj gives Im⁡ R(𝐔+iτej,D)/τ=Aej+O(τ2)\operatorname{Im}\,R(\mathbf U+i\tau e_j,D)/\tau=Ae_j+O(\tau^2), column jj of AA, without any tangent statement; an imaginary perturbation of the design gives RDekR_De_k. At the defaults, the largest differences from the columns computed by the tangent statements of Section 8 (all N+1N+1 columns of AA, all 3 columns of RDR_D) are:

重构Reconstructionmax⁡∣ACS−A∣\max|A_{\rm CS}-A|(N+1N+1 列)max⁡∣ACS−A∣\max|A_{\rm CS}-A| (N+1N+1 columns)max⁡∣RD,CS−RD∣\max|R_{D,\rm CS}-R_D|(3 列)max⁡∣RD,CS−RD∣\max|R_{D,\rm CS}-R_D| (3 columns)
一阶first order2.2e−164.4e−16
无限制器线性unlimited linear4.4e−164.4e−16
光滑限制器smooth limiter4.4e−164.4e−16

这是对第 8、9 节的又一项独立检验:前向语句给出的 A,RDA,R_D 与“只换算术”的程序一致;第 9 节的反向语句又是它们的转置(点积检验)。选一列看看:AA 的第 00 行和第 NN 行是单位行(只有对角元 11),边界节点的值不依赖别的节点;第 00、NN 列在紧邻的行里也有元素(边界节点通过斜率和扩散进入相邻的行),内部的列在 j−2j-2 到 j+2j+2 行非零;RDR_D 的第 00、NN 行是 −duin/dDk-\mathrm du_{\rm in}/\mathrm dD_k 和 −duout/dDk-\mathrm du_{\rm out}/\mathrm dD_k(ν\nu 列为零)。

This is one more independent check of Sections 8 and 9: the AA and RDR_D of the tangent statements agree with the program whose only change is its arithmetic, and the reverse statements of Section 9 are their transpose (the dot-product test). Pick a column: rows 00 and NN of AA are unit rows (the diagonal entry 11 only), so a boundary value depends on no other node; columns 00 and NN also have entries in the neighbouring rows (the boundary node enters them through the slopes and the diffusion), the interior columns are nonzero in rows j−2j-2 to j+2j+2; rows 00 and NN of RDR_D hold −duin/dDk-\mathrm du_{\rm in}/\mathrm dD_k and −duout/dDk-\mathrm du_{\rm out}/\mathrm dD_k (zero in the ν\nu column).

代价与局限

Cost and limits

  • 每个分量一次复数求解(中心差分要两次实数求解);复数运算比实数贵几倍(一次复数乘法是 4 次实数乘法);不用调步长,τ=10−30\tau=10^{-30} 永远可用。One complex solve per component (the central difference needs two real ones); complex arithmetic costs a few times more than real (one complex multiplication is 4 real ones); no step to tune: τ=10−30\tau=10^{-30} always works.
  • 要求代码是解析的,并且要有一个复数版本的残差;遇到 ∣u∣|u|、max⁡\max、限制器开关要逐个分析。It needs the code to be analytic and a complex version of the residual; an ∣u∣|u|, a max⁡\max or a limiter switch must be analysed one by one.
  • 和差分一样,求解次数随设计分量数增长,而伴随一次求解给出全部分量;它验证的也是 JhJ_h 的导数,不回答离散误差的问题(第 15 节)。Like the difference, its number of solves grows with the number of design components, where the adjoint gives all of them with one solve; and it too verifies the derivative of JhJ_h, not the discretisation error (Section 15).
第 15 节Section 15

精度阶:网格加密下的误差

Order of accuracy: the errors under refinement

本节实验:先预测,网格加密一倍(N→2NN\to2N),无限制器线性格式的误差缩小几倍?一阶格式呢?从 N=8N=8 到 1616 就能看到吗?三个梯度分量的误差也像状态误差那样表现良好吗?然后用收敛实验和加密播放器检验。

Experiment: predict first: when the mesh is refined once (N→2NN\to2N), by what factor does the error of the unlimited linear scheme shrink, and that of the first-order scheme? Can you see it already from N=8N=8 to 1616? Do the errors of the three gradient components behave as well as the state error? Then check with the convergence lab and the refinement player.

第 13、14 节检验了导数:伴随梯度就是 JhJ_h 的导数(差分验证到误差不超过 10−910^{-9},复数步长到舍入水平)。本节问另一个问题:网格加密时,离散解、离散目标和离散梯度是否趋向构造解的精确值,趋向得多快。不同网格上的 JhJ_h 是不同的函数,所以必须先在每个网格上把非线性方程解到舍入水平,再看离散误差。

Sections 13 and 14 checked the derivatives: the adjoint gradient is the derivative of JhJ_h (to 10−910^{-9} or better by differences, to rounding by the complex step). This section asks a different question: as the mesh is refined, do the discrete solution, objective and gradient approach the exact values of the manufactured solution, and how fast? JhJ_h on different meshes are different functions, so on every mesh the nonlinear equations are first solved to rounding and only then is the discretisation error measured.

量什么、和什么比

What is measured, against what

未知量是节点上的点值,所以 UjU_j 与精确的节点值 u∗(xj)u^*(x_j) 比较(没有单元平均;第 2 节),目标与 J∗J^* 比较,梯度与第 1 节的精确梯度比较。观测阶是相邻两套网格的误差之比以 2 为底的对数,写在细网格 NN 的那一行(errN\mathrm{err}_N 是 NN 个区间的网格上的某个误差):

The unknowns are point values at the nodes, so UjU_j is compared with the exact nodal values u∗(xj)u^*(x_j) (there are no cell averages; Section 2), the objective with J∗J^* and the gradient with the exact gradient of Section 1. The observed order is the base-2 logarithm of the ratio of the errors on two successive meshes, printed in the row of the finer mesh NN (errN\mathrm{err}_N is one of these errors on the mesh with NN intervals):

∥𝐔−u∗∥1=h∑j=0N∣Uj−u∗(xj)∣,∥𝐔−u∗∥∞=max⁡j∣Uj−u∗(xj)∣,∣Jh−J∗∣,∣Dˉk−∂kJ∗∣,ord=log⁡2errN/2errN.\|\mathbf U-u^*\|_1=h\sum_{j=0}^{N}|U_j-u^*(x_j)|,\quad \|\mathbf U-u^*\|_\infty=\max_j|U_j-u^*(x_j)|,\quad |J_h-J^*|,\quad |\bar D_k-\partial_kJ^*|,\qquad \mathrm{ord}=\log_2\frac{\mathrm{err}_{N/2}}{\mathrm{err}_N}.

两个边界节点由约束行定为 U0=uinU_0=u_{\rm in}、UN=uoutU_N=u_{\rm out},对 ℓ1\ell^1 误差没有贡献。格点格式与格心格式有一个重要的区别:目标的权重 wj=Wj(1+xj)w_j=W_j(1+x_j) 是梯形公式,所以哪怕状态是精确的节点值,JhJ_h 也不等于 J∗J^*。对精确节点值,Euler–Maclaurin 公式((1+x)u∗(1+x)u^* 的导数在两端相差 ux∗(0)u^*_x(0),因为 u∗u^* 是周期的)给出 Jh(u∗)−J∗=h212 ux∗(0)+O(h4)J_h(u^*)-J^*=\tfrac{h^2}{12}\,u^*_x(0)+O(h^4):N=8N=8 时实测与第一项之比是 1.01041.0104,去掉第一项后的余项在 N=16N=16 到 128128 的观测阶在 4.00 与 4.02 之间。这个量只含 u∗u^*,三种重构的值完全相同。

The two boundary nodes are fixed by the constraint rows, U0=uinU_0=u_{\rm in} and UN=uoutU_N=u_{\rm out}, and add nothing to the ℓ1\ell^1 error. There is one important difference from the cell-centred scheme: the objective weights wj=Wj(1+xj)w_j=W_j(1+x_j) are the trapezoid rule, so even with the exact nodal values as the state JhJ_h is not J∗J^*. For the exact nodal values the Euler–Maclaurin formula (the derivative of (1+x)u∗(1+x)u^* differs by ux∗(0)u^*_x(0) between the two ends, because u∗u^* is periodic) gives Jh(u∗)−J∗=h212 ux∗(0)+O(h4)J_h(u^*)-J^*=\tfrac{h^2}{12}\,u^*_x(0)+O(h^4): at N=8N=8 the measured value over the first term is 1.01041.0104, and the remainder after the first term has an observed order between 4.00 and 4.02 from N=16N=16 to 128128. This quantity contains only u∗u^*, so its value is identical for the three reconstructions.

于是目标误差分成两部分,梯度误差也一样:

So the objective error has two parts, and the gradient error splits the same way:

Jh−J∗=[Jh(u∗)−J∗]+wT(𝐔−u∗),Dˉk−∂kJ∗=[∑jwj ∂ku∗(xj)−∂kJ∗]+wT(vk−∂ku∗).\begin{aligned}J_h-J^*&=\bigl[J_h(u^*)-J^*\bigr]+w^T(\mathbf U-u^*),\\ \bar D_k-\partial_kJ^*&=\Bigl[\sum_jw_j\,\partial_ku^*(x_j)-\partial_kJ^*\Bigr]+w^T(v_k-\partial_ku^*).\end{aligned}

方括号是权重(梯形公式)的误差,与格式无关;其余是格式的:目标里是 𝐔−u∗\mathbf U-u^* 的加权和,梯度里是切线解 vkv_k 的误差的加权和。梯度的权重部分对 aa 约为 h212 ∂aux∗(0)\tfrac{h^2}{12}\,\partial_a u^*_x(0),同样是 O(h2)O(h^2)。u∗u^* 与 ν\nu 无关,所以 ∂νu∗=0\partial_\nu u^*=0,ν\nu 分量的权重部分恰好为 0,它的误差就是离散梯度 Dˉν=∂νJh\bar D_\nu=\partial_\nu J_h 本身。图 78 把默认设计下无限制器线性的三个量拆开:除 N=512N=512(两部分几乎抵消)外,每套网格上格式的部分都比梯形部分大,目标大 1.97 到 10.56 倍(aa 分量 1.89 到 10.51 倍,φ\varphi 分量 2.62 到 76.69 倍);N=8N=8 时梯形误差占目标误差的 21%,N=4096N=4096 时占 45%(aa 分量:22% 与 48%)。梯形部分不能忽略,尤其是目标和 aa 分量;下面几小节讨论格式的部分。

The brackets are the error of the weights (the trapezoid rule), which does not depend on the scheme; the rest belongs to the scheme: a weighted sum of 𝐔−u∗\mathbf U-u^* for the objective, a weighted sum of the error of the tangent solution vkv_k for the gradient. The part of the weights of the gradient is for aa about h212 ∂aux∗(0)\tfrac{h^2}{12}\,\partial_a u^*_x(0), again O(h2)O(h^2). As u∗u^* does not depend on ν\nu, ∂νu∗=0\partial_\nu u^*=0: the part of the weights of the ν\nu-component is exactly 0 and its error is the discrete gradient Dˉν=∂νJh\bar D_\nu=\partial_\nu J_h itself. Figure 78 splits the three quantities for unlimited linear at the defaults: on every mesh except N=512N=512 (where the two parts nearly cancel) the part of the scheme is larger than the trapezoid part, by a factor of 1.97 to 10.56 for the objective (1.89 to 10.51 for the aa-component, 2.62 to 76.69 for the φ\varphi-component); the trapezoid error is 21% of the objective error at N=8N=8 and 45% at N=4096N=4096 (for the aa-component 22% and 48%). The trapezoid part cannot be neglected, least of all for the objective and the aa-component; the subsections below deal with the part of the scheme.

图 78 · 目标误差与梯度误差拆成权重的梯形误差和格式的部分(无限制器线性,默认设计,N=8 到 4096;绝对值)。方块:总误差;圈(虚线):权重(梯形公式)的部分,二阶;点:格式的部分。除 N=512(目标与 a 分量的两部分几乎抵消)外,格式的部分(点)都高于梯形部分(圈);两者最终都按斜率 2 下降,符号见表。10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​区间数 N误差的绝对值83212851220482目标 Jh​ − J*总误差权重(梯形公式)的部分格式的部分10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​区间数 N误差的绝对值83212851220482梯度 a 分量总误差权重(梯形公式)的部分格式的部分10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​1区间数 N误差的绝对值83212851220482梯度 φ 分量总误差权重(梯形公式)的部分格式的部分
图 78 · 目标误差与梯度误差拆成权重的梯形误差和格式的部分(无限制器线性,默认设计,N=8N=8 到 40964096;绝对值)。方块:总误差;圈(虚线):权重(梯形公式)的部分,二阶;点:格式的部分。除 N=512N=512(目标与 aa 分量的两部分几乎抵消)外,格式的部分(点)都高于梯形部分(圈);两者最终都按斜率 2 下降,符号见表。
Figure 78 · The objective and gradient errors split into the trapezoid error of the weights and the part of the scheme (unlimited linear, default design, N=8 to 4096; absolute values). Squares: the total error; rings (dashed): the part of the weights (trapezoid rule), second order; dots: the part of the scheme. Except at N=512 (where the two parts of the objective and of the a-component nearly cancel) the part of the scheme (dots) lies above the trapezoid part (rings); both end up falling with slope 2; the signs are in the table.10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​intervals Nabsolute error83212851220482objective Jh​ − J*total errorpart of the weights (trapezoid rule)part of the scheme10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​intervals Nabsolute error83212851220482gradient component atotal errorpart of the weights (trapezoid rule)part of the scheme10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​1intervals Nabsolute error83212851220482gradient component φtotal errorpart of the weights (trapezoid rule)part of the scheme
Figure 78 · The objective and gradient errors split into the trapezoid error of the weights and the part of the scheme (unlimited linear, default design, N=8N=8 to 40964096; absolute values). Squares: the total error; rings (dashed): the part of the weights (trapezoid rule), second order; dots: the part of the scheme. Except at N=512N=512 (where the two parts of the objective and of the aa-component nearly cancel) the part of the scheme (dots) lies above the trapezoid part (rings); both end up falling with slope 2; the signs are in the table.
目标 Jh−J∗J_h-J^*Objective Jh−J∗J_h-J^*梯度 aa 分量Gradient component aa梯度 φ\varphi 分量Gradient component φ\varphi
NN总total梯形trapezoid格式scheme总total梯形trapezoid格式scheme总total梯形trapezoid格式scheme
8−7.3e−31.5e−3−8.7e−3−3.4e−27.5e−3−4.2e−23.3e−1−4.4e−33.4e−1
642.4e−42.3e−52.2e−41.2e−31.2e−41.1e−32.6e−3−6.8e−52.7e−3
5121.5e−73.6e−7−2.1e−77.7e−71.8e−6−1.0e−6−1.7e−5−1.1e−6−1.6e−5
4096−1.3e−85.6e−9−1.8e−8−5.9e−82.8e−8−8.7e−8−4.6e−7−1.7e−8−4.5e−7

格式的内部:一阶就是多了黏性 hh

The scheme in the interior: first order is extra viscosity hh

先看一阶重构(迹等于节点值,斜率为零)。每一个内部行 1≤j≤N−11\le j\le N-1(边界面也是普通的面)都是

First the first-order reconstruction (the traces are the nodal values, the slopes are zero). Every row 1≤j≤N−11\le j\le N-1 (the boundary faces are ordinary faces) is

Rj=14(Uj+12−Uj−12)−(1+νh)(Uj+1−2Uj+Uj−1)−(Qj−Qj−1).R_j=\tfrac14\bigl(U_{j+1}^2-U_{j-1}^2\bigr)-\Bigl(1+\frac{\nu}{h}\Bigr)\bigl(U_{j+1}-2U_j+U_{j-1}\bigr)-\bigl(Q_j-Q_{j-1}\bigr).

除以 hh,这正是 (12u2)x−(ν+h) uxx=s(\tfrac12u^2)_x-(\nu+h)\,u_{xx}=s 的中心差分格式:Rusanov 耗散 α/2=1\alpha/2=1 等于在物理黏性上加了一个数值黏性 hh。格式求解的是一个黏性错了 hh 的问题,所以误差是 O(h)O(h);而且 h>νh>\nu 时数值黏性比物理黏性还大(默认 N=8N=8:h=12.5νh=12.5\nu;N=100N=100 时两者相等)。无限制器线性重构时,面 ff 的耗散项是一个三阶差分,

Divided by hh, this is the central-difference scheme for (12u2)x−(ν+h) uxx=s(\tfrac12u^2)_x-(\nu+h)\,u_{xx}=s: the Rusanov dissipation α/2=1\alpha/2=1 adds a numerical viscosity hh to the physical one. The scheme solves a problem whose viscosity is wrong by hh, so its error is O(h)O(h); and for h>νh>\nu the numerical viscosity is larger than the physical one (default N=8N=8: h=12.5νh=12.5\nu; the two are equal at N=100N=100). With unlimited linear reconstruction the dissipation term of face ff is a third difference,

−(qR−qL)=14(Uf+2−3Uf+1+3Uf−Uf−1),-(q_R-q_L)=\tfrac14\bigl(U_{f+2}-3U_{f+1}+3U_f-U_{f-1}\bigr),

两个相邻的面相减,一行得到 14\tfrac14 倍的四阶差分(超黏性),没有二阶导数形式的人工黏性,内部是二阶格式。第 3 节给出并验算了这两个恒等式。把精确的节点值 u∗(xj)u^*(x_j) 代进离散方程,看残差 Rj(u∗)R_j(u^*) 有多大,就能直接量出这些结论:约束行 R0,RNR_0,R_N 恰为 0(舍入水平),第 11 至 N−1N-1 行是面通量的积分截断误差。下面分两组量:内部的行 2≤j≤N−22\le j\le N-2,和紧挨边界的两行 j=1,N−1j=1,N-1。图 79 画出它们随 NN 的变化,表是 N=2048N=2048 的值。

Two neighbouring faces subtract, so a row receives 14\tfrac14 times a fourth difference (a hyperviscosity): no artificial viscosity of second-derivative form, and the interior scheme is second order. Section 3 states and checks both identities. Insert the exact nodal values u∗(xj)u^*(x_j) into the discrete equations and look at the size of the residual Rj(u∗)R_j(u^*): that measures these conclusions directly. The constraint rows R0,RNR_0,R_N vanish (to rounding); the rows 11 to N−1N-1 are the integrated truncation errors of the face fluxes. The numbers come in two groups: the inner rows 2≤j≤N−22\le j\le N-2 and the two rows next to the boundary, j=1,N−1j=1,N-1. Figure 79 draws them against NN; the table lists the values at N=2048N=2048.

格式Scheme内部行 max⁡∣Rj∣\max|R_j|(N=2048N=2048)inner rows max⁡∣Rj∣\max|R_j| (N=2048N=2048)阶order第 11、N−1N-1 行(N=2048N=2048)rows 11, N−1N-1 (N=2048N=2048)阶order
一阶first order1.9e−62.008.1e−72.01
无限制器线性unlimited linear7.7e−103.002.9e−72.00
光滑限制器smooth limiter1.9e−62.004.0e−40.98
无限制器线性,边界斜率 00unlimited linear, boundary slope 007.7e−103.004.0e−41.00
无限制器线性,三点单侧差分unlimited linear, three-point one-sided7.7e−103.001.4e−93.00

读表(阶是 N=1024→2048N=1024\to2048 的观测阶):一阶每一行都是 O(h2)O(h^2)(2.00,2.01);这个残差是积分量,除以 hh 才是截断密度,它是 O(h)O(h),所以格式是一阶的。无限制器线性内部行是 O(h3)O(h^3)(观测阶 3.00),紧挨边界的两行是 O(h2)O(h^2)(2.00):边界节点上的单侧斜率 σ0=U1−U0\sigma_0=U_1-U_0 只有一阶精度,边界面的通量只有 O(h2)O(h^2)。光滑限制器内部行是 O(h2)O(h^2)(2.00),紧挨边界的两行在 N=32N=32 到 256256 都在 1.9×10−31.9\times10^{-3} 到 2.6×10−32.6\times10^{-3} 之间,不随 NN 变小:边界节点的斜率不经限制器,而内部的斜率被 ϵ\epsilon 压小(后面“光滑限制器”小节),两者的差成了这两行的主要误差。把边界节点的斜率改成 00(边界节点不重构)时这两行降为 O(h)O(h)(1.00),改成三点单侧差分 12(−3U0+4U1−U2)\tfrac12(-3U_0+4U_1-U_2) 时升为 O(h3)O(h^3)(3.00);本页取的两点单侧差分正好在中间。这三种边界斜率是本节后面的实验,不是本页的格式。独立的 Python 程序在 N=32N=32 到 40964096 报告的 exact_nodal_residual_inner_rows_inf 和 ..._boundary_rows_inf 与这里的值(相对)相差不到 10−1210^{-12}。

Reading the table (orders are the observed orders for N=1024→2048N=1024\to2048): first order is O(h2)O(h^2) in every row (2.00, 2.01); the residual is an integrated quantity, and the truncation density, divided by hh, is O(h)O(h), so the scheme is first order. Unlimited linear is O(h3)O(h^3) in the inner rows (observed order 3.00) and O(h2)O(h^2) in the two rows next to the boundary (2.00): the one-sided slope σ0=U1−U0\sigma_0=U_1-U_0 at the boundary node is only first-order accurate, and the flux of the boundary face is accurate only to O(h2)O(h^2). The smooth limiter is O(h2)O(h^2) in the inner rows (2.00), but the two rows next to the boundary lie between 1.9×10−31.9\times10^{-3} and 2.6×10−32.6\times10^{-3} for all N=32N=32 to 256256, not shrinking with NN: the slope at the boundary node does not pass through the limiter, while the interior slopes are pushed down by ϵ\epsilon (subsection "The smooth limiter" below), and the mismatch becomes the main error of these two rows. With the slope of the boundary node set to 00 (the boundary nodes not reconstructed) the two rows drop to O(h)O(h) (1.00), with the three-point one-sided difference 12(−3U0+4U1−U2)\tfrac12(-3U_0+4U_1-U_2) they rise to O(h3)O(h^3) (3.00); the two-point one-sided difference of this page lies in between. These three boundary slopes are an experiment of the later part of this section, not the page's scheme. The independent Python program reports exact_nodal_residual_inner_rows_inf and ..._boundary_rows_inf for N=32N=32 to 40964096, and they differ from the values here (relatively) by less than 10−1210^{-12}.

图 79 · 精确节点值的残差,按行分组(默认设计,N=8 到 2048):实线是内部行 2 ≤ j ≤ N-2 的最大值,虚线是第 1、N-1 行的最大值;方块:无限制器线性,圈:一阶,点:光滑限制器。三角形标出斜率 2 和 3。无限制器线性的内部行按 h^3、边界旁的行按 h^2 下降;一阶各行按 h^2;光滑限制器的边界旁的行在 N ≤ 256 不下降。10-10​10-8​10-6​10-4​10-2​1区间数 Nmax |Rj​(u*)|832128512204823一阶无限制器线性光滑限制器实线:内部的行(2 … N−2)虚线:第 1 行与第 N−1 行
图 79 · 精确节点值的残差,按行分组(默认设计,N=8N=8 到 20482048):实线是内部行 2≤j≤N−22\le j\le N-2 的最大值,虚线是第 11、N−1N-1 行的最大值;方块:无限制器线性,圈:一阶,点:光滑限制器。三角形标出斜率 2 和 3。无限制器线性的内部行按 h3h^3、边界旁的行按 h2h^2 下降;一阶各行按 h2h^2;光滑限制器的边界旁的行在 N≤256N\le256 不下降。
Figure 79 · The residual of the exact nodal values, by groups of rows (default design, N=8 to 2048): solid lines are the maximum over the inner rows 2 ≤ j ≤ N-2, dashed lines the maximum over rows 1 and N-1; squares: unlimited linear, rings: first order, dots: smooth limiter. The triangles mark slopes 2 and 3. For unlimited linear the inner rows fall like h^3 and the rows next to the boundary like h^2; first order falls like h^2 in every row; the rows next to the boundary of the smooth limiter do not fall for N ≤ 256.10-10​10-8​10-6​10-4​10-2​1intervals Nmax |Rj​(u*)|832128512204823first orderunlimited linearsmooth limitersolid: inner rows (2 … N−2)dashed: rows 1 and N−1
Figure 79 · The residual of the exact nodal values, by groups of rows (default design, N=8N=8 to 20482048): solid lines are the maximum over the inner rows 2≤j≤N−22\le j\le N-2, dashed lines the maximum over rows 11 and N−1N-1; squares: unlimited linear, rings: first order, dots: smooth limiter. The triangles mark slopes 2 and 3. For unlimited linear the inner rows fall like h3h^3 and the rows next to the boundary like h2h^2; first order falls like h2h^2 in every row; the rows next to the boundary of the smooth limiter do not fall for N≤256N\le256.

三种重构,N=8N=8 到 40964096

Three reconstructions, N=8N=8 to 40964096

图 80 与下面的表是本页的模型在 N=8,16,…,4096N=8,16,\dots,4096 上的结果(默认设计;每个网格都用与上方控件相同的 Newton 迭代解到舍入水平,线性方程用带状 LU 求解)。读法:

Figure 80 and the tables below are the results of this page's model on N=8,16,…,4096N=8,16,\dots,4096 (default design; every mesh solved to rounding by the Newton iteration of the controls above, the linear systems by a banded LU). How to read them:

  • 一阶:状态误差的观测阶从 0.79(N=16N=16)、0.97(N=32N=32)升到 N≥64N\ge64 的 1.01 并停在 1(N=4096N=4096:1.00)。First order: the observed order of the state error climbs from 0.79 (N=16N=16) and 0.97 (N=32N=32) to 1.01 at N≥64N\ge64 and stays at 1 (N=4096N=4096: 1.00).
  • 无限制器线性:从第一次加密起就是二阶:N=16N=16 到 40964096 的每一次加密,状态误差的观测阶都在 1.89 到 2.22 之间,N≥512N\ge512 时在 1.99 到 2.04 之间。格心格式的无限制器线性在同样的 N=16N=16、3232 只有 0.94、1.00(对精确单元平均),要到 N≥1024N\ge1024 才不低于 1.8:格心页把粗网格上的一阶表现归于它的端单元(那一页第 15 节的端单元实验),格点格式没有端单元。Unlimited linear: second order from the first refinement on: for every refinement from N=16N=16 to 40964096 the observed order of the state error lies between 1.89 and 2.22, and between 1.99 and 2.04 for N≥512N\ge512. The unlimited linear scheme of the cell-centred page shows only 0.94 and 1.00 at the same N=16N=16, 3232 (against the exact cell averages) and reaches 1.8 only from N≥1024N\ge1024: the cell-centred page traces the first-order look of its coarse meshes to its end cells (the end-cell experiment in Section 15 of that page), and this scheme has no end cells.
  • 光滑限制器:状态误差在 N=32N=32 到 256256 之间停在 2.5×10−32.5\times10^{-3} 到 3.1×10−33.1\times10^{-3}(不单调),之后下降,N=4096N=4096 时观测阶为 0.98,误差与一阶格式只差 1.3%:它在细网格上退化为一阶格式(见本节后面)。Smooth limiter: the state error stays between 2.5×10−32.5\times10^{-3} and 3.1×10−33.1\times10^{-3} for N=32N=32 to 256256 (not monotone) and then falls; at N=4096N=4096 its order is 0.98 and its error differs from the first-order one by only 1.3%: on fine meshes it degenerates to the first-order scheme (later in this section).
  • 最大范数:∥𝐔−u∗∥∞\|\mathbf U-u^*\|_\infty 与 ℓ1\ell^1 范数讲的是同一件事(收敛实验里两个都可以选):无限制器线性在 N=16N=16 到 40964096 的观测阶在 1.83 到 2.36 之间,N≥512N\ge512 时在 1.90 到 1.98 之间;一阶在 0.77 到 1.02 之间;光滑限制器在 N=4096N=4096 是 0.98。The maximum norm: ∥𝐔−u∗∥∞\|\mathbf U-u^*\|_\infty tells the same story as the ℓ1\ell^1 norm (the convergence lab offers both): for unlimited linear the observed orders for N=16N=16 to 40964096 lie between 1.83 and 2.36, and between 1.90 and 1.98 for N≥512N\ge512; first order lies between 0.77 and 1.02; the smooth limiter ends at 0.98 at N=4096N=4096.
  • 目标误差会变号:无限制器线性的 Jh−J∗J_h-J^* 在 N=8N=8 与 1616 之间、N=512N=512 与 10241024 之间变号,所以那里的“阶”没有意义;本节的表只在两个误差同号的网格之间写阶。The objective error changes sign: for unlimited linear Jh−J∗J_h-J^* changes sign between N=8N=8 and 1616 and between N=512N=512 and 10241024, so the "order" means nothing there; the tables of this section print an order only between two meshes on which the error has the same sign.
图 80 · 三种重构的加密(本页模型,默认设计,N=8 到 4096)。上:状态误差 ‖U-u*‖_1(对精确节点值;圈:一阶,方块:无限制器线性,点:光滑限制器);下:目标误差 |J_h-J*|(点:误差为正,圈:为负;颜色同上:橙一阶,蓝无限制器线性,紫光滑限制器);三角形标出斜率 1 和 2。无限制器线性的状态误差从第一次加密起就是二阶(它的目标误差两次过零,只在同号的两个网格之间标阶:1.40、2.16、2.63、3.17、4.83、1.20、1.72);光滑限制器从 N=2048 起贴到一阶的线上(状态误差和梯度 a 分量的误差与一阶相差都不到 5%)。10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​1区间数 N‖U − u*‖1​832128512204821状态误差(对精确节点值)一阶无限制器线性光滑限制器10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​1区间数 N|Jh​ − J*|83212851220482目标误差(圈:误差为负)一阶无限制器线性光滑限制器
图 80 · 三种重构的加密(本页模型,默认设计,N=8N=8 到 40964096)。上:状态误差 ∥𝐔−u∗∥1\|\mathbf U-u^*\|_1(对精确节点值;圈:一阶,方块:无限制器线性,点:光滑限制器);下:目标误差 ∣Jh−J∗∣|J_h-J^*|(点:误差为正,圈:为负;颜色同上:橙一阶,蓝无限制器线性,紫光滑限制器);三角形标出斜率 1 和 2。无限制器线性的状态误差从第一次加密起就是二阶(它的目标误差两次过零,只在同号的两个网格之间标阶:1.40、2.16、2.63、3.17、4.83、1.20、1.72);光滑限制器从 N=2048N=2048 起贴到一阶的线上(状态误差和梯度 aa 分量的误差与一阶相差都不到 5%)。
Figure 80 · Refinement of the three reconstructions (this page's model, default design, N=8 to 4096). Top: the state error ‖U-u*‖_1 (against the exact nodal values; rings: first order, squares: unlimited linear, dots: smooth limiter); bottom: the objective error |J_h-J*| (dots: the error is positive, rings: negative; the colours as above: orange first order, blue unlimited linear, violet smooth limiter); the triangles mark slopes 1 and 2. The state error of unlimited linear is second order from the first refinement on (its objective error passes through zero twice, so its orders are printed only between meshes of the same sign: 1.40, 2.16, 2.63, 3.17, 4.83, 1.20, 1.72); from N=2048 on the smooth limiter lies on the first-order line (its state error and the error of its gradient component a are within 5% of first order's).10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​1intervals N‖U − u*‖1​832128512204821state error (against the exact nodal values)first orderunlimited linearsmooth limiter10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​1intervals N|Jh​ − J*|83212851220482objective error (rings: the error is negative)first orderunlimited linearsmooth limiter
Figure 80 · Refinement of the three reconstructions (this page's model, default design, N=8N=8 to 40964096). Top: the state error ∥𝐔−u∗∥1\|\mathbf U-u^*\|_1 (against the exact nodal values; rings: first order, squares: unlimited linear, dots: smooth limiter); bottom: the objective error ∣Jh−J∗∣|J_h-J^*| (dots: the error is positive, rings: negative; the colours as above: orange first order, blue unlimited linear, violet smooth limiter); the triangles mark slopes 1 and 2. The state error of unlimited linear is second order from the first refinement on (its objective error passes through zero twice, so its orders are printed only between meshes of the same sign: 1.40, 2.16, 2.63, 3.17, 4.83, 1.20, 1.72); from N=2048N=2048 on the smooth limiter lies on the first-order line (its state error and the error of its gradient component aa are within 5% of first order's).
一阶first order无限制器线性unlimited linear光滑限制器smooth limiter
NN∥𝐔−u∗∥1\|\mathbf U-u^*\|_1ord\mathrm{ord}∥𝐔−u∗∥1\|\mathbf U-u^*\|_1ord\mathrm{ord}∥𝐔−u∗∥1\|\mathbf U-u^*\|_1ord\mathrm{ord}
81.3e−1—1.3e−2—2.4e−2—
167.5e−20.792.9e−32.226.9e−31.81
323.8e−20.977.7e−41.902.5e−31.44
641.9e−21.011.8e−42.062.7e−3−0.07
1289.4e−31.014.1e−52.153.1e−3−0.22
2564.7e−31.019.6e−62.102.9e−30.12
5122.3e−31.002.3e−62.031.9e−30.55
10241.2e−31.005.9e−72.001.1e−30.84
20485.8e−41.001.5e−71.995.7e−40.94
40962.9e−41.003.7e−82.002.9e−40.98
一阶first order无限制器线性unlimited linear光滑限制器smooth limiter
NNJh−J∗J_h-J^*ord\mathrm{ord}Jh−J∗J_h-J^*ord\mathrm{ord}Jh−J∗J_h-J^*ord\mathrm{ord}
8−1.9e−1—−7.3e−3—−8.5e−3—
16−1.1e−10.742.8e−3—1.7e−3—
32−5.9e−20.951.1e−31.405.1e−41.71
64−3.0e−21.002.4e−42.16−1.3e−3—
128−1.5e−21.013.9e−52.63−3.3e−3−1.35
256−7.4e−31.014.3e−63.17−4.1e−3−0.30
512−3.7e−31.001.5e−74.83−3.0e−30.46
1024−1.8e−31.00−9.5e−8—−1.7e−30.81
2048−9.2e−41.00−4.1e−81.20−8.8e−40.93
4096−4.6e−41.00−1.3e−81.72−4.5e−40.97

自己做一遍:选重构和误差量,网格从 N=8N=8 加密到 40964096(当前设计,在浏览器里计算;带状 LU 使每个网格的求解只需几毫秒)。梯度误差带符号:圈表示误差为负。还可以换一种边界斜率(本节后面的实验)。

Do it yourself: pick a reconstruction and an error, refine from N=8N=8 to 40964096 (the current design, computed in the browser; the banded LU keeps every solve to milliseconds). The gradient errors are signed: a ring means a negative error. You can also change the boundary slope (the experiment later in this section).

加密播放器一次只显示一个网格:离散解与精确节点值、误差的分布,以及到这一步为止的收敛曲线。

The refinement player shows one mesh at a time: the discrete solution against the exact nodal values, the distribution of the error, and the convergence curve up to this step.

梯度误差不单调:它们会变号

The gradient errors are not monotone: they change sign

状态误差表现良好,梯度误差则不然:带符号的误差 Dˉk−∂kJ∗\bar D_k-\partial_kJ^* 随 NN 变号,误差在其间变号的两套网格之间,“观测阶”可以是负数,也可以远大于 2,没有意义。图 81(无限制器线性与一阶;N≤4096N\le4096 是本页的模型,N>4096N>4096 是独立的 Python 程序)和下面的表给出带符号的误差。无限制器线性:aa 分量在 N=8N=8 与 1616 之间、N=512N=512 与 10241024 之间变号,φ\varphi 分量在 N=128N=128 与 256256 之间变号,ν\nu 分量在 N=8N=8 与 1616 之间、N=1024N=1024 与 20482048 之间变号;一阶:φ\varphi 分量在 N=16N=16 与 3232 之间变号,ν\nu 分量在 N=64N=64 与 128128 之间变号;光滑限制器:aa 分量在 N=8N=8 与 1616 之间、N=128N=128 与 256256 之间变号,φ\varphi 分量在 N=32N=32 与 6464 之间、N=256N=256 与 512512 之间变号。所以三个分量的观测阶要到很细的网格上才可信:无限制器线性中,观测阶从 N=8192N=8192(aa)、N=4096N=4096(φ\varphi)、N=16384N=16384(ν\nu)起才不低于 1.8;N=16384N=16384 时三个分量是 1.94、1.98、1.85,一阶是 1.00、1.00、0.99。不要用一个观测阶概括梯度误差:先看误差序列和符号,再看同号的网格之间的阶。

The state error is a well-behaved quantity, the gradient errors are not: the signed error Dˉk−∂kJ∗\bar D_k-\partial_kJ^* changes sign as NN grows, and between two meshes with a zero in between the "observed order" can be negative or far above 2 and means nothing. Figure 81 (unlimited linear and first order; N≤4096N\le4096 is this page's model, N>4096N>4096 the independent Python program) and the table below give the signed errors. Unlimited linear: the aa-component changes sign between N=8N=8 and 1616 and between N=512N=512 and 10241024; the φ\varphi-component changes sign between N=128N=128 and 256256; the ν\nu-component changes sign between N=8N=8 and 1616 and between N=1024N=1024 and 20482048. First order: the φ\varphi-component changes sign between N=16N=16 and 3232; the ν\nu-component changes sign between N=64N=64 and 128128. Smooth limiter: the aa-component changes sign between N=8N=8 and 1616 and between N=128N=128 and 256256; the φ\varphi-component changes sign between N=32N=32 and 6464 and between N=256N=256 and 512512. So the observed orders of the three components can be trusted only on very fine meshes: for unlimited linear the observed order stays at or above 1.8 only from N=8192N=8192 (aa), N=4096N=4096 (φ\varphi) and N=16384N=16384 (ν\nu); at N=16384N=16384 the three components show 1.94, 1.98 and 1.85, first order 1.00, 1.00 and 0.99. Do not sum up a gradient error by one observed order: look at the error sequence and its signs first, then at the orders between meshes of the same sign.

图 81 · 带符号的梯度误差(默认设计):无限制器线性(蓝)与一阶(橙,虚线);N ≤ 4096 是本页的模型,N>4096 是 Python 程序(N=8192、16384,无限制器线性还有 65536)。点:误差为正;圈:误差为负。每个分量的曲线在符号改变的地方都有一个深谷;一阶最终贴着斜率 1,无限制器线性最终贴着斜率 2。10-10​10-8​10-6​10-4​10-2​1区间数 N误差的绝对值832128512204881923276821梯度 a 分量的误差无限制器线性一阶10-10​10-8​10-6​10-4​10-2​1区间数 N误差的绝对值832128512204881923276821梯度 φ 分量的误差无限制器线性一阶10-10​10-8​10-6​10-4​10-2​1区间数 N误差的绝对值832128512204881923276821梯度 ν 分量的误差无限制器线性一阶
图 81 · 带符号的梯度误差(默认设计):无限制器线性(蓝)与一阶(橙,虚线);N≤4096N\le4096 是本页的模型,N>4096N>4096 是 Python 程序(N=8192N=8192、1638416384,无限制器线性还有 6553665536)。点:误差为正;圈:误差为负。每个分量的曲线在符号改变的地方都有一个深谷;一阶最终贴着斜率 1,无限制器线性最终贴着斜率 2。
Figure 81 · The signed gradient errors (default design): unlimited linear (blue) and first order (orange, dashed); N ≤ 4096 is this page's model, N>4096 the Python program (N=8192, 16384, and for unlimited linear also 65536). Dots: the error is positive; rings: negative. Every component has a deep valley where its sign changes; first order ends up on slope 1, unlimited linear on slope 2.10-10​10-8​10-6​10-4​10-2​1intervals Nabsolute error832128512204881923276821gradient error, aunlimited linearfirst order10-10​10-8​10-6​10-4​10-2​1intervals Nabsolute error832128512204881923276821gradient error, φunlimited linearfirst order10-10​10-8​10-6​10-4​10-2​1intervals Nabsolute error832128512204881923276821gradient error, νunlimited linearfirst order
Figure 81 · The signed gradient errors (default design): unlimited linear (blue) and first order (orange, dashed); N≤4096N\le4096 is this page's model, N>4096N>4096 the Python program (N=8192N=8192, 1638416384, and for unlimited linear also 6553665536). Dots: the error is positive; rings: negative. Every component has a deep valley where its sign changes; first order ends up on slope 1, unlimited linear on slope 2.
梯度 aa 分量的误差error of the gradient component aa梯度 φ\varphi 分量的误差error of the gradient component φ\varphi梯度 ν\nu 分量的误差error of the gradient component ν\nu
NNDˉk−∂kJ∗\bar D_k-\partial_kJ^*ord\mathrm{ord}Dˉk−∂kJ∗\bar D_k-\partial_kJ^*ord\mathrm{ord}Dˉk−∂kJ∗\bar D_k-\partial_kJ^*ord\mathrm{ord}
8−3.41e−2—3.35e−1—3.91e−3—
161.39e−2—7.94e−22.08−6.98e−2—
325.33e−31.381.61e−22.30−3.91e−20.84
641.18e−32.172.62e−32.62−1.42e−21.46
1281.89e−42.652.61e−43.33−3.52e−32.01
2562.09e−53.18−1.55e−5—−5.97e−42.56
5127.71e−74.76−1.68e−5−0.11−7.06e−53.08
1024−4.38e−7—−5.99e−61.49−4.36e−64.02
2048−1.93e−71.19−1.73e−61.797.81e−7—
4096−5.87e−81.71−4.62e−71.904.41e−70.83
8192−1.60e−81.87−1.19e−71.951.41e−71.64
16384−4.17e−91.94−3.03e−81.983.93e−81.85
65536−2.93e−101.92−1.89e−92.002.64e−91.95

表:无限制器线性,带符号的误差;阶只写在同号的相邻网格之间,N=65536N=65536 的阶是从 1638416384 起两次加密的平均。

Table: unlimited linear, the signed errors; an order is printed only between neighbouring meshes of the same sign, and the order at N=65536N=65536 is the average of two refinements from 1638416384.

Python 程序算到 65536 个区间

The Python runs to 65536 intervals

发布仓库里的独立 Python 程序(python/burgers_viscous/node/solve_node.py,稀疏 Jacobian、SciPy 的 LU,没有用到本页的 JavaScript 模型的任何代码)把无限制器线性算到 N=16384N=16384 和 6553665536,一阶和光滑限制器算到 1638416384(图 82)。在共同的网格 N=32N=32 到 40964096 上,本页模型与 Python 程序的状态误差相差不超过 5.3×10−145.3\times10^{-14},目标误差相差不超过 2.0×10−142.0\times10^{-14},梯度误差相差不超过 3.1×10−123.1\times10^{-12}:两个程序都把 Newton 迭代解到舍入水平,差别来自舍入(Python 程序在修正量不超过 10−1310^{-13} 时停止并加上最后一个修正量,残差低于舍入下限 16εmach(1+ν/h)16\varepsilon_{\rm mach}(1+\nu/h) 时也接受试探步,N=65536N=65536 的重新求解需要这一条,N≤32768N\le32768 时有没有它结果都一样)。状态误差的观测阶在 N=16384N=16384 是:无限制器线性 2.00,一阶 1.00,光滑限制器 1.00;无限制器线性从 1638416384 到 6553665536 的平均阶是 2.00。梯度误差见上一小节。

The independent Python program of the publish repository (python/burgers_viscous/node/solve_node.py, a sparse Jacobian, SciPy's LU, not one line of this page's JavaScript model) ran unlimited linear to N=16384N=16384 and 6553665536, and first order and the smooth limiter to 1638416384 (Figure 82). On the common meshes N=32N=32 to 40964096 this page's model and the Python program differ by at most 5.3×10−145.3\times10^{-14} in the state errors, 2.0×10−142.0\times10^{-14} in the objective errors and 3.1×10−123.1\times10^{-12} in the gradient errors: both programs solve the Newton iteration to rounding, and the differences come from rounding (the Python program stops at a correction of at most 10−1310^{-13} and adds the last correction, and it also accepts a trial step when the residual is below the rounding floor 16εmach(1+ν/h)16\varepsilon_{\rm mach}(1+\nu/h), which the re-solves at N=65536N=65536 need; at N≤32768N\le32768 it changes nothing). The observed order of the state error at N=16384N=16384 is 2.00 for unlimited linear, 1.00 for first order and 1.00 for the smooth limiter; the mean order of unlimited linear from 1638416384 to 6553665536 is 2.00. The gradient errors are in the previous subsection.

Python 程序自己的梯度检验(JSON 里的 gradient_check)是以扰动前的解为初值热启动、容差取默认的 10−1310^{-13}、步长 τ=10−5\tau=10^{-5} 的完整重新求解的中心差分(沿方向 (1,0.3,0)(1,0.3,0),并沿三个坐标轴):第一个修正量约为 τ∣vk∣\tau|v_k|,远大于容差,所以不是第 13 节说的最危险的组合。沿方向的差分与它自己的伴随梯度相差 2.9×10−122.9\times10^{-12} 到 6.4×10−116.4\times10^{-11}(三种重构的所有网格)。沿坐标轴的误差也只在一处超过 10−810^{-8}:光滑限制器的 ν\nu 轴在 N=64N=64 到 512512 是 1.5×10−81.5\times10^{-8} 到 5.8×10−85.8\times10^{-8}。这是 τ2\tau^2 的截断误差(第 13 节的 V 形),换成 τ=10−6\tau=10^{-6} 就消失,见第 13 节的表。

The Python program's own gradient check (gradient_check in the JSON) is a central difference of complete re-solves at the step τ=10−5\tau=10^{-5}, warm-started from the unperturbed solution with the default tolerance 10−1310^{-13} (along the direction (1,0.3,0)(1,0.3,0) and along the three axes): the first correction is about τ∣vk∣\tau|v_k|, far above the tolerance, so this is not the most dangerous combination of Section 13. Along the direction the difference agrees with the program's own adjoint gradient to 2.9×10−122.9\times10^{-12} to 6.4×10−116.4\times10^{-11} (all meshes of the three reconstructions). Along the axes the error exceeds 10−810^{-8} in one place only: the ν\nu axis of the smooth limiter at N=64N=64 to 512512, where it is 1.5×10−81.5\times10^{-8} to 5.8×10−85.8\times10^{-8}. That is the τ2\tau^2 truncation error (the V of Section 13), and it disappears with τ=10−6\tau=10^{-6}; see the table of Section 13.

图 82 · Python 程序的加密数据(默认设计,读自经哈希校验的 JSON;误差取绝对值)。上:无限制器线性,N=32 到 65536;中:一阶;下:光滑限制器(都到 16384)。方块:状态误差;圈(紫):目标误差;实心点:梯度 a 与 ν 分量的误差;圈:梯度 φ 分量的误差。梯度 ν 分量的误差(一阶)、梯度 φ 分量的误差(无限制器线性)、状态误差(光滑限制器)、目标误差(光滑限制器)、梯度 a 分量的误差(光滑限制器)、梯度 φ 分量的误差(光滑限制器)、梯度 ν 分量的误差(光滑限制器)在粗网格上不单调。无限制器线性中 ν 分量(精确值 0)的误差从 N=8192 起一直最大。10-10​10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​区间数 N误差的绝对值3212851220488192327682无限制器线性:N = 32 … 65536(Python)状态误差目标误差梯度 a 分量梯度 φ 分量梯度 ν 分量10-6​10-5​10-4​10-3​10-2​10-1​1区间数 N误差的绝对值32128512204881921一阶:N = 32 … 16384(Python)状态误差目标误差梯度 a 分量梯度 φ 分量梯度 ν 分量10-6​10-5​10-4​10-3​10-2​10-1​1区间数 N误差的绝对值32128512204881921光滑限制器:N = 32 … 16384(Python)状态误差目标误差梯度 a 分量梯度 φ 分量梯度 ν 分量
图 82 · Python 程序的加密数据(默认设计,读自经哈希校验的 JSON;误差取绝对值)。上:无限制器线性,N=32N=32 到 6553665536;中:一阶;下:光滑限制器(都到 1638416384)。方块:状态误差;圈(紫):目标误差;实心点:梯度 aa 与 ν\nu 分量的误差;圈:梯度 φ\varphi 分量的误差。梯度 ν\nu 分量的误差(一阶)、梯度 φ\varphi 分量的误差(无限制器线性)、状态误差(光滑限制器)、目标误差(光滑限制器)、梯度 aa 分量的误差(光滑限制器)、梯度 φ\varphi 分量的误差(光滑限制器)、梯度 ν\nu 分量的误差(光滑限制器)在粗网格上不单调。无限制器线性中 ν\nu 分量(精确值 0)的误差从 N=8192N=8192 起一直最大。
Figure 82 · The refinement data of the Python program (default design, read from the hash-checked JSON; absolute values of the errors). Top: unlimited linear, N=32 to 65536; middle: first order; bottom: the smooth limiter (both to 16384). Squares: the state error; rings (violet): the objective error; dots: the errors of the gradient components a and ν; rings: the error of the gradient component φ. The error of the gradient component ν (first order), the error of the gradient component φ (unlimited linear), the state error (smooth limiter), the objective error (smooth limiter), the error of the gradient component a (smooth limiter), the error of the gradient component φ (smooth limiter), the error of the gradient component ν (smooth limiter) are not monotone on coarse meshes. For unlimited linear the ν-component (exact value 0) has the largest error from N=8192 on.10-10​10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​intervals Nabsolute error3212851220488192327682unlimited linear: N = 32 … 65536 (Python)state errorobjective errorgradient, agradient, φgradient, ν10-6​10-5​10-4​10-3​10-2​10-1​1intervals Nabsolute error32128512204881921first order: N = 32 … 16384 (Python)state errorobjective errorgradient, agradient, φgradient, ν10-6​10-5​10-4​10-3​10-2​10-1​1intervals Nabsolute error32128512204881921smooth limiter: N = 32 … 16384 (Python)state errorobjective errorgradient, agradient, φgradient, ν
Figure 82 · The refinement data of the Python program (default design, read from the hash-checked JSON; absolute values of the errors). Top: unlimited linear, N=32N=32 to 6553665536; middle: first order; bottom: the smooth limiter (both to 1638416384). Squares: the state error; rings (violet): the objective error; dots: the errors of the gradient components aa and ν\nu; rings: the error of the gradient component φ\varphi. The error of the gradient component ν\nu (first order), the error of the gradient component φ\varphi (unlimited linear), the state error (smooth limiter), the objective error (smooth limiter), the error of the gradient component aa (smooth limiter), the error of the gradient component φ\varphi (smooth limiter), the error of the gradient component ν\nu (smooth limiter) are not monotone on coarse meshes. For unlimited linear the ν\nu-component (exact value 0) has the largest error from N=8192N=8192 on.
状态State目标Objective梯度误差Gradient errors求解Solve
NN∥𝐔−u∗∥1\|\mathbf U-u^*\|_1ord\mathrm{ord}∣Jh−J∗∣|J_h-J^*|Dˉa−∂aJ∗\bar D_a-\partial_aJ^*Dˉφ−∂φJ∗\bar D_\varphi-\partial_\varphi J^*Dˉν\bar D_\nuNewton 修正Newton corr.秒seconds
327.7e−4—1.1e−35.33e−31.61e−2−3.91e−24.7e−160.0576
641.8e−42.062.4e−41.18e−32.62e−3−1.42e−24.3e−150.0205
1284.1e−52.153.9e−51.89e−42.61e−4−3.52e−32.8e−160.0209
2569.6e−62.104.3e−62.09e−5−1.55e−5−5.97e−42.8e−160.0220
5122.3e−62.031.5e−77.71e−7−1.68e−5−7.06e−52.5e−160.0251
10245.9e−72.009.5e−8−4.38e−7−5.99e−6−4.36e−62.3e−160.0323
20481.5e−71.994.1e−8−1.93e−7−1.73e−67.81e−73.4e−140.0437
40963.7e−82.001.3e−8−5.87e−8−4.62e−74.41e−72.3e−150.0676
81929.2e−92.003.4e−9−1.60e−8−1.19e−71.41e−72.8e−160.1176
163842.3e−92.008.9e−10−4.17e−9−3.03e−83.93e−81.5e−160.2155
655361.4e−102.005.7e−11−2.93e−10−1.89e−92.64e−91.3e−160.7928
状态State目标Objective梯度误差Gradient errors求解Solve
NN∥𝐔−u∗∥1\|\mathbf U-u^*\|_1ord\mathrm{ord}∣Jh−J∗∣|J_h-J^*|Dˉa−∂aJ∗\bar D_a-\partial_aJ^*Dˉφ−∂φJ∗\bar D_\varphi-\partial_\varphi J^*Dˉν\bar D_\nuNewton 修正Newton corr.秒seconds
323.8e−2—5.9e−2−3.13e−14.22e−29.22e−21.6e−160.0541
641.9e−21.013.0e−2−1.56e−13.50e−21.73e−26.8e−140.0198
1289.4e−31.011.5e−2−7.78e−22.13e−2−7.80e−53.3e−160.0212
2564.7e−31.017.4e−3−3.87e−21.17e−2−2.45e−32.1e−160.0201
5122.3e−31.003.7e−3−1.93e−26.09e−3−1.86e−31.5e−160.0227
10241.2e−31.001.8e−3−9.64e−33.11e−3−1.09e−31.5e−160.0269
20485.8e−41.009.2e−4−4.81e−31.57e−3−5.86e−41.3e−160.0361
40962.9e−41.004.6e−4−2.41e−37.90e−4−3.03e−42.3e−140.0467
81921.5e−41.002.3e−4−1.20e−33.96e−4−1.54e−41.5e−150.0792
163847.3e−51.001.1e−4−6.01e−41.98e−4−7.77e−51.7e−160.1422
状态State目标Objective梯度误差Gradient errors求解Solve
NN∥𝐔−u∗∥1\|\mathbf U-u^*\|_1ord\mathrm{ord}∣Jh−J∗∣|J_h-J^*|Dˉa−∂aJ∗\bar D_a-\partial_aJ^*Dˉφ−∂φJ∗\bar D_\varphi-\partial_\varphi J^*Dˉν\bar D_\nuNewton 修正Newton corr.秒seconds
322.5e−3—5.1e−47.17e−31.13e−2−7.43e−22.7e−160.0556
642.7e−3−0.071.3e−36.66e−3−4.68e−3−1.07e−12.9e−160.0230
1283.1e−3−0.223.3e−33.96e−3−8.18e−3−1.38e−12.2e−160.0238
2562.9e−30.124.1e−3−8.97e−3−1.60e−3−8.79e−22.7e−160.0259
5121.9e−30.553.0e−3−1.28e−22.64e−3−3.34e−22.1e−160.0302
10241.1e−30.841.7e−3−8.46e−32.37e−3−1.06e−22.0e−160.0340
20485.7e−40.948.8e−4−4.60e−31.41e−3−3.18e−31.3e−160.0479
40962.9e−40.984.5e−4−2.36e−37.53e−4−9.81e−42.2e−140.0693
81921.5e−40.992.3e−4−1.19e−33.87e−4−3.27e−41.5e−150.1237
163847.3e−51.001.1e−4−5.99e−41.96e−4−1.21e−41.8e−160.2659

三张表依次是无限制器线性(含 6553665536 个区间的一行,阶按两次加密平均)、一阶、光滑限制器;梯度误差带符号,阶见上一小节。二阶收敛不只是范数的性质:把误差分布乘以 N2N^2,四套网格的曲线逐渐重合(图 83:N2max⁡j∣Uj−u∗(xj)∣N^2\max_j|U_j-u^*(x_j)| 依次为 1.17、1.23、1.24、1.25)。

The three tables are unlimited linear (with the row of 6553665536 intervals, its orders averaged over two refinements), first order and the smooth limiter; the gradient errors are signed, and their orders are in the previous subsection. Second-order convergence is not only a property of the norms: multiplied by N2N^2, the error profiles of four meshes come together (Figure 83: N2max⁡j∣Uj−u∗(xj)∣N^2\max_j|U_j-u^*(x_j)| is 1.17, 1.23, 1.24 and 1.25).

图 83 · 误差分布乘以 N^2(无限制器线性,Python 数据,每套网格均匀抽取 161 个节点):N=1024(虚线)、4096、16384、65536(粗线)的 N^2(U_j-u*(x_j)) 逐渐重合,说明误差逐点以 h^2 收敛。N=65536 时绝对值最大的值 -1.25 位于内部 x ≈ 0.306 处;两个端点上的误差恰为 0(约束行),紧挨端点的值小而平滑(最靠近端点的两个抽样点是 -0.031 与 0.034):没有端点的尖峰。−1−0.500.500.20.40.60.81xN² (Uj​ − u*(xj​))N = 1024N = 4096N = 16384N = 65536
图 83 · 误差分布乘以 N2N^2(无限制器线性,Python 数据,每套网格均匀抽取 161 个节点):N=1024N=1024(虚线)、40964096、1638416384、6553665536(粗线)的 N2(Uj−u∗(xj))N^2(U_j-u^*(x_j)) 逐渐重合,说明误差逐点以 h2h^2 收敛。N=65536N=65536 时绝对值最大的值 −1.25-1.25 位于内部 x≈0.306x\approx0.306 处;两个端点上的误差恰为 0(约束行),紧挨端点的值小而平滑(最靠近端点的两个抽样点是 −0.031-0.031 与 0.0340.034):没有端点的尖峰。
Figure 83 · Error profiles multiplied by N^2 (unlimited linear, Python data, 161 nodes sampled evenly from each mesh): N^2(U_j-u*(x_j)) for N=1024 (dashed), 4096, 16384 and 65536 (thick) come together, so the error converges pointwise like h^2. At N=65536 the value of largest magnitude, -1.25, sits in the interior at x ≈ 0.306; the error at the two end nodes is exactly 0 (the constraint rows) and the values next to them are small and smooth (the two sampled nodes nearest to the ends are -0.031 and 0.034): there is no spike at the ends.−1−0.500.500.20.40.60.81xN² (Uj​ − u*(xj​))N = 1024N = 4096N = 16384N = 65536
Figure 83 · Error profiles multiplied by N2N^2 (unlimited linear, Python data, 161 nodes sampled evenly from each mesh): N2(Uj−u∗(xj))N^2(U_j-u^*(x_j)) for N=1024N=1024 (dashed), 40964096, 1638416384 and 6553665536 (thick) come together, so the error converges pointwise like h2h^2. At N=65536N=65536 the value of largest magnitude, −1.25-1.25, sits in the interior at x≈0.306x\approx0.306; the error at the two end nodes is exactly 0 (the constraint rows) and the values next to them are small and smooth (the two sampled nodes nearest to the ends are −0.031-0.031 and 0.0340.034): there is no spike at the ends.

图 84 是程序在 JSON 里记录的每个网格的耗时(记录的平台字符串 macOS-26.6.2-arm64-arm-64bit 只写了操作系统和处理器架构,不是机器型号)。一个网格的耗时包括 Newton 求解、三个前向求解与一个伴随求解、差分检验的完整重新求解(四个方向,每个方向两次);三个加密文件(refinement_*.json)里的各个网格还包括与连续伴随的比较(求解一个连续伴随的边值问题),6553665536 个区间的那次单独运行不含这一项。稀疏 LU 使耗时大致随 NN 线性增长:6553665536 个区间 0.79 秒。

Figure 84 shows the time per mesh that the program recorded in the JSON (the recorded platform string, macOS-26.6.2-arm64-arm-64bit, names the operating system and the architecture, not the machine). The time of a mesh includes the Newton solve, three tangent solves and one adjoint solve, and the solves of the difference check (two full re-solves per direction, along four directions); the meshes of the three refinement files (refinement_*.json) also include the comparison with the continuous adjoint (the solution of the continuous-adjoint boundary-value problem), and the row of 6553665536 intervals (a separate run) does not. The sparse LU keeps the time roughly linear in NN: 0.79 seconds for 6553665536 intervals.

图 84 · Python 程序记录的每个网格的耗时(在记录的平台上实测,不是本页浏览器的耗时;N ≤ 16384 的各点含与连续伴随的比较)。三角形标出斜率 1(线性增长)。粗网格的耗时由固定开销决定。0.0010.010.11区间数 N每个网格的耗时(秒)3212851220488192327681无限制器线性一阶光滑限制器
图 84 · Python 程序记录的每个网格的耗时(在记录的平台上实测,不是本页浏览器的耗时;N≤16384N\le16384 的各点含与连续伴随的比较)。三角形标出斜率 1(线性增长)。粗网格的耗时由固定开销决定。
Figure 84 · Seconds per mesh recorded by the Python program (measured on the recorded platform, not in this browser; the points with N ≤ 16384 include the comparison with the continuous adjoint). The triangle marks slope 1 (linear growth). On coarse meshes fixed overheads dominate.0.0010.010.11intervals Nseconds per mesh3212851220488192327681unlimited linearfirst ordersmooth limiter
Figure 84 · Seconds per mesh recorded by the Python program (measured on the recorded platform, not in this browser; the points with N≤16384N\le16384 include the comparison with the continuous adjoint). The triangle marks slope 1 (linear growth). On coarse meshes fixed overheads dominate.

观测阶如何依赖网格 Péclet 数

How the observed order depends on the mesh Péclet number

网格间距与黏性长度 ν/u\nu/u 之比就是网格 Péclet 数 Peh=uinh/ν\mathrm{Pe}_h=u_{\rm in}h/\nu(默认 ν/uin≈0.0109\nu/u_{\rm in}\approx0.0109,N=8N=8 时 Peh=11.44\mathrm{Pe}_h=11.44)。把六个黏性 ν=0.0025, 0.005, 0.01, 0.02, 0.04, 0.08\nu=0.0025,\ 0.005,\ 0.01,\ 0.02,\ 0.04,\ 0.08 的加密以 Peh\mathrm{Pe}_h 为横轴画在一起(图 85,无限制器线性,N=8N=8 到 40964096,Peh\mathrm{Pe}_h 从 0.0028 到 23;每个点画在这一对网格中细网格的 Peh\mathrm{Pe}_h 处,最粗的网格是 45.7)。格心页上的结果是:状态误差的观测阶几乎只是 Peh\mathrm{Pe}_h 的函数,Peh>1\mathrm{Pe}_h>1 时约为 1,Peh→0\mathrm{Pe}_h\to0 时趋于 2。在格点格式上,状态误差的观测阶(N≥32N\ge32 的所有相邻网格,六个黏性)全在 1.75 与 2.22 之间:Peh>1\mathrm{Pe}_h>1 时在 1.75 到 2.21,Peh≤0.05\mathrm{Pe}_h\le0.05 时在 1.99 到 2.01。没有在 Peh=1\mathrm{Pe}_h=1 附近的过渡。同一个 Peh\mathrm{Pe}_h 处六个黏性的阶最多相差 0.22,不如格心格式齐(0.06),但相对于格心格式的阶随 Peh\mathrm{Pe}_h 的变化(Peh>1\mathrm{Pe}_h>1 时在 0.96 到 1.13,Peh≤0.05\mathrm{Pe}_h\le0.05 时在 1.91 到 2.00)很小:格点格式的阶对 Peh\mathrm{Pe}_h 的依赖远不如格心格式那样强。

The ratio of the mesh spacing to the viscous length ν/u\nu/u is the mesh Péclet number Peh=uinh/ν\mathrm{Pe}_h=u_{\rm in}h/\nu (at the defaults ν/uin≈0.0109\nu/u_{\rm in}\approx0.0109, and Peh=11.44\mathrm{Pe}_h=11.44 at N=8N=8). Draw the refinements of six viscosities ν=0.0025, 0.005, 0.01, 0.02, 0.04, 0.08\nu=0.0025,\ 0.005,\ 0.01,\ 0.02,\ 0.04,\ 0.08 with Peh\mathrm{Pe}_h as the horizontal axis (Figure 85, unlimited linear, N=8N=8 to 40964096, Peh\mathrm{Pe}_h from 0.0028 to 23; every point is drawn at the Peh\mathrm{Pe}_h of the finer mesh of its pair, and the coarsest mesh has 45.7). The result on the cell-centred page is that the observed order of the state error is almost a function of Peh\mathrm{Pe}_h alone: about 1 for Peh>1\mathrm{Pe}_h>1 and tending to 2 as Peh→0\mathrm{Pe}_h\to0. On the node-centred scheme the observed order of the state error (all neighbouring meshes with N≥32N\ge32, six viscosities) lies between 1.75 and 2.22: 1.75 to 2.21 for Peh>1\mathrm{Pe}_h>1 and 1.99 to 2.01 for Peh≤0.05\mathrm{Pe}_h\le0.05. There is no transition near Peh=1\mathrm{Pe}_h=1. At the same Peh\mathrm{Pe}_h the orders of the six viscosities differ by at most 0.22, less tidy than the cell-centred scheme (0.06), but small against the change of the cell-centred order with Peh\mathrm{Pe}_h (0.96 to 1.13 for Peh>1\mathrm{Pe}_h>1, 1.91 to 2.00 for Peh≤0.05\mathrm{Pe}_h\le0.05): the order of the node-centred scheme does not depend on Peh\mathrm{Pe}_h the way the cell-centred one does.

格心页把这个过渡归于它两端不重构的端单元(那一页的第 15 节做了端单元实验)。格点格式没有端单元:边界面用单侧斜率,边界旁的行是 O(h2)O(h^2)(上面的残差表),边界节点这一行的贡献在下一小节量出。梯度误差没有画在 Peh\mathrm{Pe}_h 图里:它们的符号随黏性变化,观测阶不可读(上一小节)。

The cell-centred page traces this transition to its two end cells, which are not reconstructed (the end-cell experiment in Section 15 of that page). The node-centred scheme has no end cells: the boundary face uses a one-sided slope and the rows next to the boundary are O(h2)O(h^2) (the residual table above); what the boundary rows contribute is measured in the next subsection. The gradient errors are not drawn in the Peh\mathrm{Pe}_h figure: their signs change with the viscosity and their observed orders cannot be read (previous subsection).

图 85 · 状态误差的观测阶与网格 Péclet 数(无限制器线性,a=0.2,φ=0.07,六个黏性,每个 N=8 到 4096;每个点画在细网格的 Pe_h 处)。上:本页的格点格式——N ≥ 32 的所有点在 1.75 与 2.22 之间(最粗一对 N=8 → 16 的六个点在 2.16 与 2.26 之间),没有过渡;下:格心页的格式(对精确单元平均)——Pe_h>1 时约为 1,Pe_h → 0 时趋于 2。00.511.522.50.010.1110细网格的 Peh​状态误差的观测阶本页(格点格式)Peh​ = 1ν = 0.0025ν = 0.005ν = 0.01ν = 0.02ν = 0.04ν = 0.0800.511.522.50.010.1110细网格的 Peh​状态误差的观测阶格心页(对精确单元平均)Peh​ = 1ν = 0.0025ν = 0.005ν = 0.01ν = 0.02ν = 0.04ν = 0.08
图 85 · 状态误差的观测阶与网格 Péclet 数(无限制器线性,a=0.2a=0.2,φ=0.07\varphi=0.07,六个黏性,每个 N=8N=8 到 40964096;每个点画在细网格的 Peh\mathrm{Pe}_h 处)。上:本页的格点格式——N≥32N\ge32 的所有点在 1.75 与 2.22 之间(最粗一对 N=8→16N=8\to16 的六个点在 2.16 与 2.26 之间),没有过渡;下:格心页的格式(对精确单元平均)——Peh>1\mathrm{Pe}_h>1 时约为 1,Peh→0\mathrm{Pe}_h\to0 时趋于 2。
Figure 85 · Observed order of the state error against the mesh Péclet number (unlimited linear, a=0.2, φ=0.07, six viscosities, each with N=8 to 4096; every point is drawn at the Pe_h of the finer mesh). Top: this page's node-centred scheme: all points with N ≥ 32 lie between 1.75 and 2.22 (the six points of the coarsest pair N=8 → 16 lie between 2.16 and 2.26), with no transition; bottom: the scheme of the cell-centred page (against the exact cell averages): about 1 for Pe_h>1, tending to 2 as Pe_h → 0.00.511.522.50.010.1110Peh​ of the finer meshobserved order of the state errorthis page (node-centred scheme)Peh​ = 1ν = 0.0025ν = 0.005ν = 0.01ν = 0.02ν = 0.04ν = 0.0800.511.522.50.010.1110Peh​ of the finer meshobserved order of the state errorthe cell-centred page (against the exact cell averages)Peh​ = 1ν = 0.0025ν = 0.005ν = 0.01ν = 0.02ν = 0.04ν = 0.08
Figure 85 · Observed order of the state error against the mesh Péclet number (unlimited linear, a=0.2a=0.2, φ=0.07\varphi=0.07, six viscosities, each with N=8N=8 to 40964096; every point is drawn at the Peh\mathrm{Pe}_h of the finer mesh). Top: this page's node-centred scheme: all points with N≥32N\ge32 lie between 1.75 and 2.22 (the six points of the coarsest pair N=8→16N=8\to16 lie between 2.16 and 2.26), with no transition; bottom: the scheme of the cell-centred page (against the exact cell averages): about 1 for Peh>1\mathrm{Pe}_h>1, tending to 2 as Peh→0\mathrm{Pe}_h\to0.

自己选几个黏性:当前的 a,φa,\varphi,每个 ν\nu 从 N=8N=8 加密到 40964096(在浏览器里计算;默认的 a,φa,\varphi 时还可画出格心格式(无限制器线性)的状态误差作对照)。

Pick some viscosities: the current a,φa,\varphi, every ν\nu refined from N=8N=8 to 40964096 (computed in the browser; at the default a,φa,\varphi the state error of the cell-centred scheme (unlimited linear) can be drawn for comparison).

边界行贡献什么

What the boundary rows contribute

格心页的端单元实验在这里没有对应物:格点格式没有端单元,两个边界节点的行是约束行。能贡献误差的是紧挨边界的第 11 行和第 N−1N-1 行:它们的面通量用边界节点上的单侧斜率 σ0=U1−U0\sigma_0=U_1-U_0(σN=UN−UN−1\sigma_N=U_N-U_{N-1})重构边界面的迹。有两种办法量出它们的贡献。第一种:换边界斜率。只在本节做的实验(不是本页的格式;这些变体的 Jacobian 用复数步长得到,所以它们的切线与伴随梯度也是精确的):把 σ0,σN\sigma_0,\sigma_N 取为 00(边界节点不重构),取为本页的两点单侧差分,取为三点单侧差分 12(−3U0+4U1−U2)\tfrac12(-3U_0+4U_1-U_2),或者取为精确的斜率 h ux∗h\,u^*_x(只是为了知道更好的边界斜率最多能带来什么)。结果见下面三条和图 86。

The end-cell experiment of the cell-centred page has no counterpart here: the node-centred scheme has no end cells, and the rows of the two boundary nodes are constraint rows. What can contribute error is rows 11 and N−1N-1, next to the boundary: their face fluxes reconstruct the trace of the boundary face with the one-sided slope σ0=U1−U0\sigma_0=U_1-U_0 (σN=UN−UN−1\sigma_N=U_N-U_{N-1}) of the boundary node. Two ways measure their contribution. The first: change the boundary slope. An experiment of this section only (not the page's scheme; the Jacobians of the variants come from the complex step, so their tangent and adjoint gradients are exact too): take σ0,σN\sigma_0,\sigma_N equal to 00 (the boundary nodes are not reconstructed), to the two-point one-sided difference of this page, to the three-point one-sided difference 12(−3U0+4U1−U2)\tfrac12(-3U_0+4U_1-U_2), or to the exact slope h ux∗h\,u^*_x (only to learn what a better boundary slope could gain at most). The results are in the three items below and in Figure 86.

  • 斜率取 0:状态误差大得多,而且只慢慢地进入二阶:N=8N=8 时是本页的 6.2 倍,N=2048N=2048 时是 120 倍;观测阶从 N=16N=16 的 1.15 升到 N=2048N=2048 的 1.94。Slope 00: the state error is much larger and enters second order only slowly: 6.2 times that of the page at N=8N=8 and 120 times at N=2048N=2048; its observed order rises from 1.15 at N=16N=16 to 1.94 at N=2048N=2048.
  • 三点单侧差分:N≥256N\ge256 时状态误差与本页的相差不到 1.4%(N=128N=128 时 8.0%);梯度 aa 分量的误差在 N=2048N=2048 是 −2.9×10−7-2.9\times10^{-7}(本页是 −1.9×10−7-1.9\times10^{-7}),观测阶 2.05(本页 1.19):它从 N=256N=256 起就是干净的二阶,本页的则迟迟没有。Three-point one-sided difference: for N≥256N\ge256 its state error differs from the page's by less than 1.4% (8.0% at N=128N=128); the error of the gradient component aa is −2.9×10−7-2.9\times10^{-7} at N=2048N=2048 (the page's is −1.9×10−7-1.9\times10^{-7}) with an observed order of 2.05 (the page's 1.19): second order is clean from N=256N=256, the page's takes much longer.
  • 精确的斜率:N≥512N\ge512 时状态误差与三点单侧差分的相差不到 0.1%:再好的边界斜率也不会带来更多。The exact slope: for N≥512N\ge512 its state error differs from that of the three-point difference by less than 0.1%: no better boundary slope would bring more.
图 86 · 边界节点的斜率(无限制器线性,默认设计,N=8 到 2048)。上:状态误差;下:梯度 a 分量的误差(点:正,圈:负)。橙:斜率取 0;蓝:本页的两点单侧差分;紫:三点单侧差分。斜率取 0 时状态误差大得多,只在很细的网格上才贴近二阶;三点单侧差分的梯度误差从 N=256 起就是二阶,本页的在 N=512 与 1024 之间变号,以后才逐渐趋向二阶。三角形标出斜率 1 和 2。10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​区间数 N‖U − u*‖1​832128512204821状态误差(无限制器线性)边界节点斜率取 0本页:两点单侧差分三点单侧差分10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​1区间数 N误差的绝对值83212851220482梯度 a 分量的误差(圈:误差为负)边界节点斜率取 0本页:两点单侧差分三点单侧差分
图 86 · 边界节点的斜率(无限制器线性,默认设计,N=8N=8 到 20482048)。上:状态误差;下:梯度 aa 分量的误差(点:正,圈:负)。橙:斜率取 00;蓝:本页的两点单侧差分;紫:三点单侧差分。斜率取 00 时状态误差大得多,只在很细的网格上才贴近二阶;三点单侧差分的梯度误差从 N=256N=256 起就是二阶,本页的在 N=512N=512 与 10241024 之间变号,以后才逐渐趋向二阶。三角形标出斜率 1 和 2。
Figure 86 · The slope at the boundary nodes (unlimited linear, default design, N=8 to 2048). Top: the state error; bottom: the error of the gradient component a (dots: positive, rings: negative). Orange: slope 0; blue: the page's two-point one-sided difference; violet: the three-point one-sided difference. With slope 0 the state error is much larger and approaches second order only on very fine meshes; the gradient error of the three-point difference is second order from N=256, that of the page changes sign between N=512 and 1024 and approaches second order only afterwards. The triangles mark slopes 1 and 2.10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​intervals N‖U − u*‖1​832128512204821state error (unlimited linear)boundary slope 0the page: two-point one-sidedthree-point one-sided10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​1intervals Nabsolute error83212851220482error of the gradient component a (rings: negative)boundary slope 0the page: two-point one-sidedthree-point one-sided
Figure 86 · The slope at the boundary nodes (unlimited linear, default design, N=8N=8 to 20482048). Top: the state error; bottom: the error of the gradient component aa (dots: positive, rings: negative). Orange: slope 00; blue: the page's two-point one-sided difference; violet: the three-point one-sided difference. With slope 00 the state error is much larger and approaches second order only on very fine meshes; the gradient error of the three-point difference is second order from N=256N=256, that of the page changes sign between N=512N=512 and 10241024 and approaches second order only afterwards. The triangles mark slopes 1 and 2.

第二种:伴随加权残差。状态误差由残差决定:R(𝐔)=0R(\mathbf U)=0 而 R(u∗)≠0R(u^*)\ne0,在 u∗u^* 处展开 0=R(u∗)+A e+O(∥e∥2)0=R(u^*)+A\,e+O(\|e\|^2)(e=𝐔−u∗e=\mathbf U-u^*),所以 e=−A−1R(u∗)+O(∥e∥2)e=-A^{-1}R(u^*)+O(\|e\|^2)。乘上 wTw^T,并用第 11 节的伴随方程 ATψ=−wA^T\psi=-w(ψT=−wTA−1\psi^T=-w^TA^{-1}):

The second: the adjoint-weighted residual. The state error is set by the residual: R(𝐔)=0R(\mathbf U)=0 while R(u∗)≠0R(u^*)\ne0; expanding about u∗u^* gives 0=R(u∗)+A e+O(∥e∥2)0=R(u^*)+A\,e+O(\|e\|^2) (e=𝐔−u∗e=\mathbf U-u^*), so e=−A−1R(u∗)+O(∥e∥2)e=-A^{-1}R(u^*)+O(\|e\|^2). Multiply by wTw^T and use the adjoint equation ATψ=−wA^T\psi=-w of Section 11 (ψT=−wTA−1\psi^T=-w^TA^{-1}):

Jh(𝐔)−Jh(u∗)=wTe=ψTR(u∗)+O(∥e∥2)=∑j=1N−1ψj Rj(u∗)+O(∥e∥2).J_h(\mathbf U)-J_h(u^*)=w^Te=\psi^TR(u^*)+O(\|e\|^2)=\sum_{j=1}^{N-1}\psi_j\,R_j(u^*)+O(\|e\|^2).

格式给目标带来的误差,就是精确节点值的残差被伴随 ψ\psi 加权后的和:每一行贡献 ψjRj(u∗)\psi_jR_j(u^*)(约束行的残差为 0,不贡献)。右边用本页的伴随解 ψ\psi 和精确节点值的残差算出,与左边 Jh(𝐔)−Jh(u∗)J_h(\mathbf U)-J_h(u^*) 的比值在 N=8N=8 是 1.02741.0274,N≥128N\ge128 时与 1 相差不超过 4.5×10−54.5\times10^{-5}。把这个和分成两部分:紧挨边界的第 11、N−1N-1 行,和内部各行(图 87,下表)。第 11 行的乘子 ψ1\psi_1 只有在伴随的边界层被分辨(h≪ν/uin≈0.0109h\ll\nu/u_{\rm in}\approx0.0109)之后才像 hλx(0)h\lambda_x(0) 那样小:连续伴随 λ\lambda(附录 A)满足 λ(0)=0\lambda(0)=0,λx(0)=−142.66\lambda_x(0)=-142.66,而 ψj\psi_j 近似 λ(xj)\lambda(x_j)(第 16 节把二者比较),所以细网格上 ψ1≈h λx(0)\psi_1\approx h\,\lambda_x(0):实测 ψ1/(hλx(0))\psi_1/(h\lambda_x(0)) 在 N=64,512,4096N=64,512,4096 是 0.549、0.944、0.994(∣ψ1∣|\psi_1| 在 N=8,64,512,4096N=8,64,512,4096 是 1.71、1.22、0.26、0.035)。因此渐近地,第 1 行的截断误差 R1(u∗)=O(hp)R_1(u^*)=O(h^p) 对目标的代价是 O(hp+1)O(h^{p+1}):本页 p=2p=2,得 h3h^3(边界行贡献的观测阶 2.992.99),斜率取 00 时 p=1p=1,得 h2h^2(1.971.97),三点单侧差分 p=3p=3,得 h4h^4(4.004.00);内部各行是 h2h^2(2.022.02)。

The error that the scheme brings to the objective is the sum of the residual of the exact nodal values weighted by the adjoint ψ\psi: every row contributes ψjRj(u∗)\psi_jR_j(u^*) (the residuals of the constraint rows are 0 and contribute nothing). The right-hand side, computed from this page's adjoint solution ψ\psi and the residual of the exact nodal values, over the left-hand side Jh(𝐔)−Jh(u∗)J_h(\mathbf U)-J_h(u^*) is 1.02741.0274 at N=8N=8 and differs from 1 by at most 4.5×10−54.5\times10^{-5} for N≥128N\ge128. Split the sum in two: rows 11 and N−1N-1 next to the boundary, and the inner rows (Figure 87, table below). The multiplier ψ1\psi_1 of row 1 is small like hλx(0)h\lambda_x(0) only once the layer of the adjoint is resolved (h≪ν/uin≈0.0109h\ll\nu/u_{\rm in}\approx0.0109): the continuous adjoint λ\lambda (Appendix A) has λ(0)=0\lambda(0)=0 and λx(0)=−142.66\lambda_x(0)=-142.66, and ψj\psi_j approximates λ(xj)\lambda(x_j) (Section 16 compares them), so ψ1≈h λx(0)\psi_1\approx h\,\lambda_x(0) on fine meshes: measured ψ1/(hλx(0))\psi_1/(h\lambda_x(0)) is 0.549, 0.944, 0.994 at N=64,512,4096N=64,512,4096, while ∣ψ1∣|\psi_1| is 1.71, 1.22, 0.26, 0.035 at N=8,64,512,4096N=8,64,512,4096. So asymptotically, if the truncation error R1(u∗)R_1(u^*) of row 1 is O(hp)O(h^p), its cost to the objective is O(hp+1)O(h^{p+1}): p=2p=2 for the page gives h3h^3 (observed order of the boundary-row contribution 2.992.99), p=1p=1 for slope 00 gives h2h^2 (1.971.97), p=3p=3 for the three-point difference gives h4h^4 (4.004.00); the inner rows give h2h^2 (2.022.02).

图 87 · 目标误差的来源(无限制器线性,默认设计,N=8 到 4096;绝对值)。橙黄圈:第 1、N-1 行的贡献 ψ_1R_1+ψ_(N-1)R_(N-1);蓝方块:内部各行的贡献;灰点(虚线):权重的梯形误差;紫点(虚线):格式部分 J_h(U)-J_h(u*)。上:本页的格式——边界行的贡献从 N ≈ 512 起按 h^3 下降,N=16 到 256 比内部各行大(符号相反,所以格式部分 J_h(U)-J_h(u*) 在 N=8 与 16 之间、N=256 与 512 之间过零),从 N=512 起内部各行占主导;下:边界节点斜率取 0——边界行的贡献按 h^2 下降,在每个 N 上都远大于内部各行(N=4096 时是它的 330 倍)。10-12​10-10​10-8​10-6​10-4​10-2​1区间数 N绝对值832128512204823本页的格式:一次单侧差分作边界斜率第 1、N−1 行的贡献内部各行的贡献权重的梯形误差格式部分 Jh​(U) − Jh​(u*)10-12​10-10​10-8​10-6​10-4​10-2​1区间数 N绝对值832128512204822对照:边界节点斜率取 0第 1、N−1 行的贡献内部各行的贡献权重的梯形误差格式部分 Jh​(U) − Jh​(u*)
图 87 · 目标误差的来源(无限制器线性,默认设计,N=8N=8 到 40964096;绝对值)。橙黄圈:第 11、N−1N-1 行的贡献 ψ1R1+ψN−1RN−1\psi_1R_1+\psi_{N-1}R_{N-1};蓝方块:内部各行的贡献;灰点(虚线):权重的梯形误差;紫点(虚线):格式部分 Jh(𝐔)−Jh(u∗)J_h(\mathbf U)-J_h(u^*)。上:本页的格式——边界行的贡献从 N≈512N\approx512 起按 h3h^3 下降,N=16N=16 到 256256 比内部各行大(符号相反,所以格式部分 Jh(𝐔)−Jh(u∗)J_h(\mathbf U)-J_h(u^*) 在 N=8N=8 与 1616 之间、N=256N=256 与 512512 之间过零),从 N=512N=512 起内部各行占主导;下:边界节点斜率取 00——边界行的贡献按 h2h^2 下降,在每个 NN 上都远大于内部各行(N=4096N=4096 时是它的 330 倍)。
Figure 87 · Where the objective error comes from (unlimited linear, default design, N=8 to 4096; absolute values). Amber rings: the contribution ψ_1R_1+ψ_(N-1)R_(N-1) of rows 1 and N-1; blue squares: the contribution of the inner rows; grey dots (dashed): the trapezoid error of the weights; violet dots (dashed): the scheme part J_h(U)-J_h(u*). Top: the page's scheme: the boundary rows' contribution falls like h^3 from N ≈ 512 on, is larger than that of the inner rows for N=16 to 256 (with the opposite sign, so the scheme part J_h(U)-J_h(u*) passes through zero between N=8 and 16 and between N=256 and 512) and from N=512 on the inner rows dominate; bottom: boundary slope 0: the boundary rows' contribution falls like h^2 and is far larger than that of the inner rows at every N (330 times at N=4096).10-12​10-10​10-8​10-6​10-4​10-2​1intervals Nabsolute value832128512204823the page: the two-point one-sided boundary sloperows 1 and N−1inner rowstrapezoid error of the weightsscheme part Jh​(U) − Jh​(u*)10-12​10-10​10-8​10-6​10-4​10-2​1intervals Nabsolute value832128512204822for contrast: boundary slope 0rows 1 and N−1inner rowstrapezoid error of the weightsscheme part Jh​(U) − Jh​(u*)
Figure 87 · Where the objective error comes from (unlimited linear, default design, N=8N=8 to 40964096; absolute values). Amber rings: the contribution ψ1R1+ψN−1RN−1\psi_1R_1+\psi_{N-1}R_{N-1} of rows 11 and N−1N-1; blue squares: the contribution of the inner rows; grey dots (dashed): the trapezoid error of the weights; violet dots (dashed): the scheme part Jh(𝐔)−Jh(u∗)J_h(\mathbf U)-J_h(u^*). Top: the page's scheme: the boundary rows' contribution falls like h3h^3 from N≈512N\approx512 on, is larger than that of the inner rows for N=16N=16 to 256256 (with the opposite sign, so the scheme part Jh(𝐔)−Jh(u∗)J_h(\mathbf U)-J_h(u^*) passes through zero between N=8N=8 and 1616 and between N=256N=256 and 512512) and from N=512N=512 on the inner rows dominate; bottom: boundary slope 00: the boundary rows' contribution falls like h2h^2 and is far larger than that of the inner rows at every NN (330330 times at N=4096N=4096).
本页的格式The page边界斜率 00Boundary slope 00
NNJh(𝐔)−Jh(u∗)J_h(\mathbf U)-J_h(u^*)第 1、N−1 行rows 1, N−1内部各行inner rows估计 / 实际estimate / actualJh(𝐔)−Jh(u∗)J_h(\mathbf U)-J_h(u^*)第 1、N−1 行rows 1, N−1内部各行inner rows估计 / 实际estimate / actual
162.5e−36.1e−3−3.7e−30.9953−5.6e−2−5.3e−2−3.7e−31.0167
642.2e−43.5e−4−1.3e−40.9998−1.1e−2−1.0e−2−1.3e−41.0019
2562.9e−69.1e−6−6.2e−61.0000−1.3e−3−1.3e−3−6.1e−61.0001
1024−1.8e−71.6e−7−3.4e−71.0000−1.0e−4−1.0e−4−3.4e−71.0000
4096−1.8e−82.5e−9−2.1e−81.0000−6.9e−6−6.8e−6−2.1e−81.0000

所以:本页的两点单侧斜率够用——状态误差从 N≥256N\ge256 起与三点单侧差分的几乎一样,最终的阶是二——但它在粗网格上给目标和梯度误差带来一个三阶的、系数不小的项,使 N≲512N\lesssim512 时观测阶忽高忽低;边界节点不重构(斜率取 00)则代价高得多。这一点与格心格式相反:格心页上不重构的端单元正是粗网格上误差的主要来源。

So: the page's two-point one-sided slope suffices (the state error is almost that of the three-point difference from N≥256N\ge256, and the final order is two), but on coarse meshes it brings a third-order term with a sizeable coefficient into the objective and gradient errors, which makes the observed orders erratic for N≲512N\lesssim512; not reconstructing the boundary nodes (slope 00) costs much more. That is the opposite of the cell-centred scheme, where the end cells that are not reconstructed are the main source of the error on coarse meshes.

自己试:选一个 NN 和边界斜率,看每一行的贡献 ψjRj(u∗)\psi_jR_j(u^*) 沿 xx 的分布,和它们的和与真实的误差比较。

Try it: pick an NN and a boundary slope and look at the contribution ψjRj(u∗)\psi_jR_j(u^*) of every row along xx, and at their sum against the real error.

固定 ϵ\epsilon 的光滑限制器在细网格上是一阶的

With a fixed ϵ\epsilon the smooth limiter is first order on fine meshes

光滑限制器的分母里有一个固定的 ϵ=0.01\epsilon=0.01。网格加密时单侧差 lj,rj≈h uxl_j,r_j\approx h\,u_x 越来越小,一旦比 ϵ\epsilon 小,就有

The denominator of the smooth limiter contains a fixed ϵ=0.01\epsilon=0.01. Under refinement the one-sided differences lj,rj≈h uxl_j,r_j\approx h\,u_x keep shrinking, and once they are smaller than ϵ\epsilon,

∣σj∣=∣lj rj (lj+rj)∣lj2+rj2+ϵ2≤∣lj rj (lj+rj)∣ϵ2=O(h3).|\sigma_j|=\frac{|l_j\,r_j\,(l_j+r_j)|}{l_j^2+r_j^2+\epsilon^2}\le\frac{|l_j\,r_j\,(l_j+r_j)|}{\epsilon^2}=O(h^3).

斜率修正 σj/2\sigma_j/2 变成 O(h3)O(h^3),迹与一阶格式的迹只差 O(h3)O(h^3),格式的主误差就是一阶格式的 O(h)O(h)。转折发生在 ∣ux∣h≈ϵ|u_x|h\approx\epsilon,即 N≈2πa/ϵ≈126N\approx2\pi a/\epsilon\approx126。图 88 在每个网格的解上量光滑斜率与中心斜率之比(内部节点的中位数):N=8N=8 时 0.78,先升到 N=32N=32 的 0.91,然后一路降到 N=4096N=4096 的 9.4×10−49.4\times10^{-4}(N=256N=256 时 0.19,512512 时 0.057,从 10241024 起不超过 0.015)。边界节点的斜率 σ0=U1−U0\sigma_0=U_1-U_0 不经过限制器:内部斜率被 ϵ\epsilon 压小以后,第 11、N−1N-1 行的边界面与相邻的内部面不再匹配,这就是上面残差表里这两行在 N≤256N\le256 不下降的原因之一(残差表只量了这一点,没有分离出别的原因)。

The slope correction σj/2\sigma_j/2 becomes O(h3)O(h^3), the traces differ from the first-order ones by O(h3)O(h^3), and the leading error of the scheme is the O(h)O(h) error of the first-order scheme. The switch happens at ∣ux∣h≈ϵ|u_x|h\approx\epsilon, i.e. N≈2πa/ϵ≈126N\approx2\pi a/\epsilon\approx126. Figure 88 measures the ratio of the smooth slope to the central slope on the solution of every mesh (the median over the interior nodes): 0.78 at N=8N=8, it first rises to 0.91 at N=32N=32, then falls all the way to 9.4×10−49.4\times10^{-4} at N=4096N=4096 (0.19 at N=256N=256, 0.057 at 512512, at most 0.015 from 10241024 on). The slope σ0=U1−U0\sigma_0=U_1-U_0 of the boundary node does not pass through the limiter: once the interior slopes are pushed down by ϵ\epsilon, the boundary face of rows 11 and N−1N-1 no longer matches its interior neighbour, which is one reason why these two rows of the residual table do not fall for N≤256N\le256 (the residual table measures only that, and does not separate other reasons).

图 88 · 光滑限制器自动“关掉”重构(默认设计,各网格自己的解)。纵轴:光滑斜率与中心斜率 (l_j+r_j)/2 之比的中位数。竖线 N=2π a/ε 处单侧差与 ε 同量级;更细的网格上这个比值迅速下降,格式退化为一阶。00.250.50.7518321285122048区间数 Nσ光​滑 / σ中​心(中位数)N = 2πa/ϵ ≈ 126光滑限制器的斜率 / 中心斜率
图 88 · 光滑限制器自动“关掉”重构(默认设计,各网格自己的解)。纵轴:光滑斜率与中心斜率 (lj+rj)/2(l_j+r_j)/2 之比的中位数。竖线 N=2πa/ϵN=2\pi a/\epsilon 处单侧差与 ϵ\epsilon 同量级;更细的网格上这个比值迅速下降,格式退化为一阶。
Figure 88 · The smooth limiter switches the reconstruction off by itself (default design, the solution of each mesh). Vertical axis: the median ratio of the smooth slope to the central slope (l_j+r_j)/2. At the vertical line N=2π a/ε the one-sided differences are of the size of ε; on finer meshes the ratio falls quickly and the scheme degenerates to first order.00.250.50.7518321285122048intervals Nσsmooth​ / σcentral​ (median)N = 2πa/ϵ ≈ 126smooth-limiter slope / central slope
Figure 88 · The smooth limiter switches the reconstruction off by itself (default design, the solution of each mesh). Vertical axis: the median ratio of the smooth slope to the central slope (lj+rj)/2(l_j+r_j)/2. At the vertical line N=2πa/ϵN=2\pi a/\epsilon the one-sided differences are of the size of ϵ\epsilon; on finer meshes the ratio falls quickly and the scheme degenerates to first order.

格点格式与格心格式:相同 N 上的比较

Node-centred against cell-centred at equal N

两个格式解同一个问题,用同样的面通量、同样的三种重构和同样的目标与设计。这里比较相同 NN(区间数)上的误差;格点格式有 N+1N+1 个未知量,格心格式有 NN 个。状态误差各对自己的精确值(节点值,单元平均);目标误差和梯度误差对同一个连续的 J∗J^* 和 ∇J∗\nabla J^*,所以梯度的比较是直接的。下表是两者误差之比(格点 / 格心;小于 1 表示格点格式的误差更小),格心格式用格心页的模型算出(本页的构建阶段)。结果取决于重构、分量和 NN,没有一个统一的结论(图 89 画出三个梯度分量的误差曲线):

The two schemes solve the same problem with the same face flux, the same three reconstructions and the same objective and design. The comparison here is of the errors at equal NN (the number of intervals); the node-centred scheme has N+1N+1 unknowns, the cell-centred scheme NN. The state errors are each against their own exact values (nodal values, cell averages); the objective and gradient errors are against the same continuous J∗J^* and ∇J∗\nabla J^*, so the comparison of the gradients is direct. The table lists the ratios of the errors (node / cell; below 1 means the node-centred error is smaller), the cell-centred scheme computed with the model of the cell-centred page (at the build of this page). The result depends on the reconstruction, the component and NN, and there is no single conclusion (Figure 89 draws the error curves of the three gradient components):

  • 无限制器线性:N=8N=8 时梯度 aa 分量的误差比是 0.099(格点格式小约一个量级),ν\nu 分量 0.013,但 φ\varphi 分量是 2.290(格点格式更大);N=16N=16 时 φ\varphi 分量仍是格点格式更大。从 N=32N=32 到 40964096 三个分量都是格点格式更小:aa 的比值在 3.7×10−43.7\times10^{-4} 到 0.0500.050 之间,φ\varphi 在 2.9×10−32.9\times10^{-3} 到 0.380.38,ν\nu 在 2.6×10−42.6\times10^{-4} 到 0.410.41;Python 数据在 N=32N=32 到 1638416384 的 10 套网格上也是如此。状态误差比在 6.9×10−36.9\times10^{-3} 到 0.260.26 之间(格点格式更小)。Unlimited linear: at N=8N=8 the error ratio is 0.099 for the gradient component aa (the node-centred error about an order of magnitude smaller) and 0.013 for ν\nu, but 2.290 for φ\varphi (the node-centred error is larger); at N=16N=16 the φ\varphi-component is still larger for the node-centred scheme. From N=32N=32 to 40964096 the node-centred error is smaller in all three components: the ratio of aa lies between 3.7×10−43.7\times10^{-4} and 0.0500.050, that of φ\varphi between 2.9×10−32.9\times10^{-3} and 0.380.38, that of ν\nu between 2.6×10−42.6\times10^{-4} and 0.410.41; the Python data show the same on all 10 meshes from N=32N=32 to 1638416384. The ratio of the state errors lies between 6.9×10−36.9\times10^{-3} and 0.260.26 (the node-centred error is smaller).
  • 一阶:格点格式在 aa 分量上不比格心格式好(比值在 1.001.00 到 1.721.72 之间,N=4096N=4096 时趋于 1),在 φ\varphi 分量上比值在 0.0880.088 到 5.25.2 之间(有好有坏),只在 ν\nu 分量上从 N=16N=16 起更好(N=8N=8 时更差);状态误差比在 1.001.00 到 1.481.48 之间(格点格式略大,趋于 1)。First order: the node-centred scheme is no better than the cell-centred one in the aa-component (ratio between 1.001.00 and 1.721.72, tending to 1 at N=4096N=4096), its ratio in the φ\varphi-component lies between 0.0880.088 and 5.25.2 (better in some places, worse in others), and it is better only in the ν\nu-component, from N=16N=16 on (worse at N=8N=8); the ratio of the state errors lies between 1.001.00 and 1.481.48 (the node-centred error slightly larger, tending to 1).
  • 光滑限制器:状态误差比在 0.170.17 到 1.01.0 之间,细网格上趋于 1(两个格式都变成一阶);梯度上(N≥32N\ge32),格点格式在 aa 分量上较好(比值 0.07 到 0.99),φ\varphi 分量有好有坏(0.22 到 1.31),ν\nu 分量从 N=128N=128 起更差(1.5 到 6.7)。Smooth limiter: the ratio of the state errors lies between 0.170.17 and 1.01.0 and tends to 1 on fine meshes (both schemes become first order); in the gradient (N≥32N\ge32) the node-centred scheme is better in the aa component (ratio 0.07 to 0.99), mixed in φ\varphi (0.22 to 1.31) and worse in ν\nu from N=128N=128 on (1.5 to 6.7).
NNNN重构Reconstruction梯度 aagradient aa梯度 φ\varphigradient φ\varphi梯度 ν\nugradient ν\nu目标 Jh−J∗J_h-J^*objective Jh−J∗J_h-J^*状态 ℓ1\ell^1state ℓ1\ell^1
8一阶first order1.7130.7234.0431.6731.473
8无限制器线性unlimited linear0.0992.2900.0130.1150.254
8光滑限制器smooth limiter0.0861.8491.0830.0940.343
32一阶first order1.4231.8210.1781.4351.290
32无限制器线性unlimited linear0.0500.3720.4100.0540.056
32光滑限制器smooth limiter0.0670.3211.1490.0240.176
128一阶first order1.1691.9195.1e−41.1831.130
128无限制器线性unlimited linear9.5e−30.0190.0229.9e−30.016
128光滑限制器smooth limiter0.2231.3152.6000.4690.686
512一阶first order1.0511.1790.0961.0561.043
512无限制器线性unlimited linear3.7e−49.8e−32.1e−33.6e−48.4e−3
512光滑限制器smooth limiter0.9070.7082.4520.9290.951
2048一阶first order1.0131.0430.3071.0151.012
2048无限制器线性unlimited linear1.3e−30.0132.6e−41.3e−37.1e−3
2048光滑限制器smooth limiter0.9860.9581.7200.9850.988
图 89 · 相同 N 上的梯度误差(默认设计,绝对值):实线方块是格点格式,虚线圈是格心格式;蓝:无限制器线性,橙:一阶。无限制器线性的格点格式在 N ≥ 32 时低于格心格式(φ 在 N=8、16 例外);一阶的两条曲线在 a 分量上靠得很近,在 φ 分量上 N ≥ 256 时靠得很近(N ≤ 128 时比值在 0.09 到 5.1 之间)。10-8​10-6​10-4​10-2​1区间数 N误差的绝对值8321285122048梯度 a 分量的误差格点,无限制器线性格心,无限制器线性格点,一阶格心,一阶10-8​10-6​10-4​10-2​1区间数 N误差的绝对值8321285122048梯度 φ 分量的误差格点,无限制器线性格心,无限制器线性格点,一阶格心,一阶10-8​10-6​10-4​10-2​1区间数 N误差的绝对值8321285122048梯度 ν 分量的误差格点,无限制器线性格心,无限制器线性格点,一阶格心,一阶
图 89 · 相同 NN 上的梯度误差(默认设计,绝对值):实线方块是格点格式,虚线圈是格心格式;蓝:无限制器线性,橙:一阶。无限制器线性的格点格式在 N≥32N\ge32 时低于格心格式(φ\varphi 在 N=8N=8、1616 例外);一阶的两条曲线在 aa 分量上靠得很近,在 φ\varphi 分量上 N≥256N\ge256 时靠得很近(N≤128N\le128 时比值在 0.09 到 5.1 之间)。
Figure 89 · The gradient errors at equal N (default design, absolute values): solid squares are the node-centred scheme, dashed rings the cell-centred one; blue: unlimited linear, orange: first order. The node-centred unlimited linear scheme lies below the cell-centred one for N ≥ 32 (the exception is φ at N=8, 16); the two first-order curves lie close together in the a component, and in the φ component for N ≥ 256 (the ratio is between 0.09 and 5.1 for N ≤ 128).10-8​10-6​10-4​10-2​1intervals Nabsolute error8321285122048gradient error, anode, unlimited linearcell, unlimited linearnode, first ordercell, first order10-8​10-6​10-4​10-2​1intervals Nabsolute error8321285122048gradient error, φnode, unlimited linearcell, unlimited linearnode, first ordercell, first order10-8​10-6​10-4​10-2​1intervals Nabsolute error8321285122048gradient error, νnode, unlimited linearcell, unlimited linearnode, first ordercell, first order
Figure 89 · The gradient errors at equal NN (default design, absolute values): solid squares are the node-centred scheme, dashed rings the cell-centred one; blue: unlimited linear, orange: first order. The node-centred unlimited linear scheme lies below the cell-centred one for N≥32N\ge32 (the exception is φ\varphi at N=8N=8, 1616); the two first-order curves lie close together in the aa component, and in the φ\varphi component for N≥256N\ge256 (the ratio is between 0.09 and 5.1 for N≤128N\le128).

自己选:重构和量,看两个格式的曲线和比值(默认设计;格心格式的结果是构建页面时算好的)。

Pick a reconstruction and a quantity and see the two curves and their ratio (default design; the results of the cell-centred scheme were computed when the page was built).

观测阶说明了什么,没有说明什么

What the observed orders show, and what they do not

  • 证实:状态误差的阶,无限制器线性趋于 2(Python,N=16384N=16384:2.00),一阶趋于 1(1.00),光滑限制器在细网格上趋于 1(1.00);本页模型在 N=32N=32 到 40964096 上重现了这些数据(状态误差相差不超过 5.3×10−145.3\times10^{-14},目标误差 2.0×10−142.0\times10^{-14},梯度误差 3.1×10−123.1\times10^{-12})。Confirmed: the orders of the state error: unlimited linear tends to 2 (Python, N=16384N=16384: 2.00), first order to 1 (1.00), and the smooth limiter to 1 on fine meshes (1.00); this page's model reproduces these data on N=32N=32 to 40964096 (to at most 5.3×10−145.3\times10^{-14} in the state errors, 2.0×10−142.0\times10^{-14} in the objective errors and 3.1×10−123.1\times10^{-12} in the gradient errors).
  • 梯度误差不单调。带符号的梯度误差会变号(上面的“梯度误差不单调”小节),观测阶要到很细的网格上才可读(无限制器线性:aa 从 N=8192N=8192、φ\varphi 从 N=4096N=4096、ν\nu 从 N=16384N=16384 起不低于 1.8);在那之前,只能看误差序列和符号。The gradient errors are not monotone. The signed gradient errors change sign (the subsection "The gradient errors are not monotone" above), and their observed orders can be read only on very fine meshes (unlimited linear: at or above 1.8 from N=8192N=8192 for aa, N=4096N=4096 for φ\varphi and N=16384N=16384 for ν\nu); before that, only the error sequence and the signs can be read.
  • 目标和梯度的误差里有权重的梯形误差,它与格式无关(二阶,上面的“量什么”小节),在默认设计下不能忽略。The objective and gradient errors contain the trapezoid error of the weights, which does not depend on the scheme (second order, the subsection "What is measured"), and which cannot be neglected at the default design.
  • 边界行:本页的两点单侧边界斜率足以得到二阶,但在粗网格上给误差带来一个三阶项;不重构边界节点则代价高得多(上一小节)。The boundary rows: the page's two-point one-sided boundary slope suffices for second order but brings a third-order term into the errors on coarse meshes; not reconstructing the boundary nodes costs much more (the subsection above).
  • 光滑限制器不是二阶格式。ϵ\epsilon 固定时它在细网格上退化为一阶(上一小节)。The smooth limiter is not a second-order scheme. With a fixed ϵ\epsilon it degenerates to first order on fine meshes (the subsection above).
  • 两个格式谁更好取决于重构、分量和 NN:见上面的比较,不能概括成“格点格式更精确”。Which scheme is better depends on the reconstruction, the component and NN: see the comparison above; it cannot be summed up as "the node-centred scheme is more accurate".

数据的来源

Where the data come from

本节的 Python 数字都读自下列文件;构建页面时检查每个文件记录的实现哈希与当前的 solve_node.py(SHA-256 a656f7615237a805…)一致,并且标明 mathematical_proof = false。它们和本页的计算一样是数值证据,不是数学证明。

The Python numbers of this section are read from the files below; when the page is built, the implementation hash recorded in every file is checked against the current solve_node.py (SHA-256 a656f7615237a805…), and every file must say mathematical_proof = false. Like this page's own computations, they are numerical evidence, not mathematical proof.

文件File命令Command版本 · 生成时间Version · generated环境Environment文件 SHA-256File SHA-256数学证明Mathematical proof
examples/refinement_first.jsonpython3 solve_node.py --grids 32,64,128,256,512,1024,2048,4096,8192,16384 --nu 0.01 --amplitude 0.2 --phase 0.07 --reconstruction first --gradient-check --continuous-adjoint --output examples/refinement_first.json1.0.0 · 2026-10-03T22:54:00ZPython 3.11.12 · NumPy 2.3.1 · SciPy 1.16.0
macOS-26.6.2-arm64-arm-64bit
25f2c6c6fd4e3ea6…否(false)false
examples/refinement_none.jsonpython3 solve_node.py --grids 32,64,128,256,512,1024,2048,4096,8192,16384 --nu 0.01 --amplitude 0.2 --phase 0.07 --reconstruction none --gradient-check --continuous-adjoint --output examples/refinement_none.json1.0.0 · 2026-10-03T22:53:59ZPython 3.11.12 · NumPy 2.3.1 · SciPy 1.16.0
macOS-26.6.2-arm64-arm-64bit
19cc697eb6fd3641…否(false)false
examples/refinement_smooth.jsonpython3 solve_node.py --grids 32,64,128,256,512,1024,2048,4096,8192,16384 --nu 0.01 --amplitude 0.2 --phase 0.07 --reconstruction smooth --gradient-check --continuous-adjoint --output examples/refinement_smooth.json1.0.0 · 2026-10-03T22:54:01ZPython 3.11.12 · NumPy 2.3.1 · SciPy 1.16.0
macOS-26.6.2-arm64-arm-64bit
29bd3d9e934caf31…否(false)false
examples/large_65536.jsonpython3 solve_node.py --cells 65536 --nu 0.01 --amplitude 0.2 --phase 0.07 --reconstruction none --gradient-check --output examples/large_65536.json1.0.0 · 2026-10-03T22:54:03ZPython 3.11.12 · NumPy 2.3.1 · SciPy 1.16.0
macOS-26.6.2-arm64-arm-64bit
e2aa97c827d94747…否(false)false

本节的结论都是在一个设计(a=0.2a=0.2,φ=0.07\varphi=0.07,ν=0.01\nu=0.01;Péclet 研究另有五个 ν\nu)上的数值观察。本页没有证明一般的收敛定理,也不声称这些阶对别的设计、别的源项或 ν→0\nu\to0 成立。

The conclusions of this section are numerical observations at one design (a=0.2a=0.2, φ=0.07\varphi=0.07, ν=0.01\nu=0.01; five more values of ν\nu in the Péclet study). The page proves no general convergence theorem and does not claim these orders for other designs, other sources, or ν→0\nu\to0.

第 16 节Section 16

伴随一致性:离散伴随会趋于连续伴随吗?

Adjoint consistency: does the discrete adjoint approach the continuous one?

本节实验:先估计一下,N=8N=8 时网格间距 hh 是伴随层宽 ν/uin\nu/u_{\rm in} 的 11.4 倍。入口约束行的乘子 ψ0\psi_0 离 νλx(0)=−1.4266\nu\lambda_x(0)=−1.4266 有多远——一成以内、大约一半,还是差几倍?再估计斜率 ψ1/h\psi_1/h 要多少个区间才进入 λx(0)=−142.7\lambda_x(0)=−142.7 的 10% 以内——一百个左右,还是一千个左右?然后用本节的加密播放器验证。

Experiment: Estimate first: at N=8N=8 the interval hh is 11.4 times the width ν/uin\nu/u_{\rm in} of the adjoint's layer. How far is the multiplier ψ0\psi_0 of the inlet constraint row from νλx(0)=−1.4266\nu\lambda_x(0)=−1.4266: within 10%, about half, or off by a factor? And how many intervals does the slope ψ1/h\psi_1/h need to come within 10% of λx(0)=−142.7\lambda_x(0)=−142.7, about a hundred or about a thousand? Then check with the refinement player of this section.

第 11 节解出了伴随 ψ\psi(ATψ=−gA^T\psi=-g),第 12 节用它给出离散目标 Jh(D)J_h(D) 的梯度 Dˉ=RDTψ\bar D=R_D^T\psi(精确到舍入误差)。附录 A 则从微分方程出发,推出连续伴随 λ\lambda 和连续梯度公式。两者回答不同的问题:ψ\psi 是有限网格上那段程序的导数,λ\lambda 是连续问题的导数。本节把它们放在一起比较:随网格加密,内部节点上的 ψj\psi_j 是否趋于 λ(xj)\lambda(x_j)?两个约束行的乘子 ψ0\psi_0、ψN\psi_N 趋于什么?离散梯度是否趋于连续梯度?粗网格上的差别从哪里来?

Section 11 solved for the adjoint ψ\psi (ATψ=−gA^T\psi=-g) and Section 12 used it for the gradient Dˉ=RDTψ\bar D=R_D^T\psi of the discrete objective Jh(D)J_h(D), exact up to rounding. Appendix A starts from the differential equation and derives the continuous adjoint λ\lambda and the continuous gradient formula. The two answer different questions: ψ\psi is a derivative of the program on a finite mesh, λ\lambda a derivative of the continuous problem. This section puts them side by side: does ψj\psi_j at the interior nodes approach λ(xj)\lambda(x_j) as the mesh is refined? What do the multipliers ψ0\psi_0, ψN\psi_N of the two constraint rows approach? Does the discrete gradient approach the continuous one? Where do the differences on coarse meshes come from?

连续伴随与连续梯度

The continuous adjoint and the continuous gradient

连续伴随(附录 A 用变分逐步推出)是一个线性两点边值问题。连续梯度有两部分:源项积分和边界项。这里 u=u∗u=u^*,∂Dku∗\partial_{D_k}u^* 在 x=0x=0、x=1x=1 处就是边界值 uinu_{\rm in}、uoutu_{\rm out} 的导数:

The continuous adjoint (derived step by step with variations in Appendix A) solves a linear two-point boundary-value problem. The continuous gradient has two parts, a source integral and a boundary term. Here u=u∗u=u^*, and ∂Dku∗\partial_{D_k}u^* at x=0x=0 and x=1x=1 is the derivative of the boundary values uinu_{\rm in}, uoutu_{\rm out}:

−u λx−ν λxx=−(1+x),λ(0)=λ(1)=0;dJdDk=−∫01λ ∂Dks dx+ν[λx ∂Dku∗]01(k=0,1).-u\,\lambda_x-\nu\,\lambda_{xx}=-(1+x),\quad \lambda(0)=\lambda(1)=0;\qquad \frac{\mathrm dJ}{\mathrm dD_k}=-\int_0^1\lambda\,\partial_{D_k}s\,\mathrm dx+\nu\Bigl[\lambda_x\,\partial_{D_k}u^*\Bigr]_0^1\quad(k=0,1).

对 D2=νD_2=\nu,通量本身含 ν\nu,公式变为 −∫01λ (∂νs+uxx∗) dx-\int_0^1\lambda\,(\partial_\nu s+u^*_{xx})\,\mathrm dx;对这一族构造解它等于零。伴随方程的对流项 −uλx-u\lambda_x 与状态方程符号相反:λ\lambda 从 x=1x=1 向 x=0x=0 传播,所以 λ(0)=0\lambda(0)=0 要靠 x=0x=0 处宽约 ν/uin=0.0109\nu/u_{\rm in}=0.0109 的边界层来满足。默认设计下(201 个点的 Chebyshev 配点),λx(0)=−142.657\lambda_x(0)=−142.657,λx(1)=2.2035\lambda_x(1)=2.2035;源项积分为 (0.4728, 1.7323)(0.4728,\ 1.7323),边界项为 (−0.6168, −1.6471)(−0.6168,\ −1.6471),两者之和与精确梯度 (−0.1440, 0.0852)(−0.1440,\ 0.0852) 相差 10−1310^{-13} 量级(本页和 Python 审计都核对过)。注意两部分都是 O(1)O(1),梯度却小得多:它是两个大数之差。

For D2=νD_2=\nu the flux itself contains ν\nu and the formula becomes −∫01λ (∂νs+uxx∗) dx-\int_0^1\lambda\,(\partial_\nu s+u^*_{xx})\,\mathrm dx, which is zero for this family. The convection term −uλx-u\lambda_x of the adjoint equation has the opposite sign of the primal one: λ\lambda travels from x=1x=1 towards x=0x=0, so λ(0)=0\lambda(0)=0 is met by a boundary layer at x=0x=0 of width about ν/uin=0.0109\nu/u_{\rm in}=0.0109. At the defaults (Chebyshev collocation on 201 points) λx(0)=−142.657\lambda_x(0)=−142.657 and λx(1)=2.2035\lambda_x(1)=2.2035; the source integral is (0.4728, 1.7323)(0.4728,\ 1.7323), the boundary term (−0.6168, −1.6471)(−0.6168,\ −1.6471), and their sum differs from the exact gradient (−0.1440, 0.0852)(−0.1440,\ 0.0852) by about 10−1310^{-13} (checked by this page and by the Python audit). Note that both parts are O(1)O(1) while the gradient is much smaller: it is the difference of two large numbers.

约束行的乘子就是连续伴随的边界通量

The multipliers of the constraint rows are the boundary fluxes of the continuous adjoint

格点格式里两个边界行是约束 R0=U0−uinR_0=U_0-u_{\rm in}、RN=UN−uoutR_N=U_N-u_{\rm out}(第 4 节),它们的乘子 ψ0\psi_0、ψN\psi_N 是伴随向量的两个分量,没有连续伴随中的点值与之对应。先在连续问题里看一看:把边界条件也当作约束,用乘子 μ0\mu_0、μ1\mu_1 写拉格朗日函数,λ\lambda 仍满足 λ(0)=λ(1)=0\lambda(0)=\lambda(1)=0:

On the node-centred mesh the two boundary rows are the constraints R0=U0−uinR_0=U_0-u_{\rm in} and RN=UN−uoutR_N=U_N-u_{\rm out} (Section 4), and their multipliers ψ0\psi_0, ψN\psi_N are two components of the adjoint vector that have no point value of λ\lambda to correspond to. Look first at the continuous problem: treat the boundary conditions as constraints too, with multipliers μ0\mu_0, μ1\mu_1 in the Lagrangian, while λ(0)=λ(1)=0\lambda(0)=\lambda(1)=0 still holds:

ℒ=J(u)+∫01λ (qx−s) dx+μ0(u(0)−uin)+μ1(u(1)−uout).\mathcal L=J(u)+\int_0^1\lambda\,(q_x-s)\,\mathrm dx+\mu_0\bigl(u(0)-u_{\rm in}\bigr)+\mu_1\bigl(u(1)-u_{\rm out}\bigr).

对状态 uu 做变分(这是连续推导,所以用 δ\delta):δq=u δu−ν δux\delta q=u\,\delta u-\nu\,\delta u_x,对 λ(δq)x\lambda(\delta q)_x 分部积分两次并用 λ(0)=λ(1)=0\lambda(0)=\lambda(1)=0,得到

Vary the state uu (this is a continuous derivation, so δ\delta is used): δq=u δu−ν δux\delta q=u\,\delta u-\nu\,\delta u_x; integrating λ(δq)x\lambda(\delta q)_x by parts twice and using λ(0)=λ(1)=0\lambda(0)=\lambda(1)=0 gives

δℒ=∫01(1+x−uλx−νλxx) δu dx+(μ0−νλx(0)) δu(0)+(μ1+νλx(1)) δu(1).\delta\mathcal L=\int_0^1\bigl(1+x-u\lambda_x-\nu\lambda_{xx}\bigr)\,\delta u\,\mathrm dx+\bigl(\mu_0-\nu\lambda_x(0)\bigr)\,\delta u(0)+\bigl(\mu_1+\nu\lambda_x(1)\bigr)\,\delta u(1).

δℒ=0\delta\mathcal L=0 对任意 δu\delta u 成立,给出伴随方程,并且乘子等于边界通量:μ0=νλx(0)\mu_0=\nu\lambda_x(0),μ1=−νλx(1)\mu_1=-\nu\lambda_x(1)。梯度是

δℒ=0\delta\mathcal L=0 for every δu\delta u gives the adjoint equation and shows that the multipliers are the boundary fluxes: μ0=νλx(0)\mu_0=\nu\lambda_x(0), μ1=−νλx(1)\mu_1=-\nu\lambda_x(1). The gradient is

dJdDk=∂Dkℒ=−∫01λ ∂Dks dx−μ0 ∂Dkuin−μ1 ∂Dkuout,\frac{\mathrm dJ}{\mathrm dD_k}=\partial_{D_k}\mathcal L=-\int_0^1\lambda\,\partial_{D_k}s\,\mathrm dx-\mu_0\,\partial_{D_k}u_{\rm in}-\mu_1\,\partial_{D_k}u_{\rm out},

也就是上面的公式。离散拉格朗日函数是

the formula above. The discrete Lagrangian is

ℒh=Jh(𝐔)+ψTR(𝐔,D)=∑j=0NwjUj+∑j=1N−1ψj[Hj−Hj−1−(Qj−Qj−1)]+ψ0 (U0−uin)+ψN (UN−uout).\mathcal L_h=J_h(\mathbf U)+\psi^TR(\mathbf U,D)=\sum_{j=0}^{N}w_jU_j+\sum_{j=1}^{N-1}\psi_j\bigl[H_j-H_{j-1}-(Q_j-Q_{j-1})\bigr]+\psi_0\,(U_0-u_{\rm in})+\psi_N\,(U_N-u_{\rm out}).

逐项对照。内部行 RjR_j 是对偶控制体 VjV_j 上的积分残差,Rj≈∫Vj(qx−s) dxR_j\approx\int_{V_j}(q_x-s)\,\mathrm dx,同样 wjUj≈∫Vj(1+x) u dxw_jU_j\approx\int_{V_j}(1+x)\,u\,\mathrm dx;所以 ψj≈λ(xj)\psi_j\approx\lambda(x_j):同号,没有因子 hh(伴随方程也对得上:(ATψ)j≈h (−uλx−νλxx)(xj)(A^T\psi)_j\approx h\,(-u\lambda_x-\nu\lambda_{xx})(x_j),右端项 −gj=−h(1+xj)-g_j=-h(1+x_j);如果残差除以控制体宽度成为“密度”形式,乘子就会变成 hλh\lambda,比较之前要先确认这种约定)。两个约束行的单位缩放使 ψ0↔μ0\psi_0\leftrightarrow\mu_0、ψN↔μ1\psi_N\leftrightarrow\mu_1,期望是 ψ0→νλx(0)\psi_0\to\nu\lambda_x(0),ψN→−νλx(1)\psi_N\to-\nu\lambda_x(1);梯度的离散与连续形式也就一一对应:

Term by term. An interior row RjR_j is an integrated residual over the dual volume VjV_j, Rj≈∫Vj(qx−s) dxR_j\approx\int_{V_j}(q_x-s)\,\mathrm dx, and likewise wjUj≈∫Vj(1+x) u dxw_jU_j\approx\int_{V_j}(1+x)\,u\,\mathrm dx; so ψj≈λ(xj)\psi_j\approx\lambda(x_j), with the same sign and no factor hh (the adjoint equations match too: (ATψ)j≈h (−uλx−νλxx)(xj)(A^T\psi)_j\approx h\,(-u\lambda_x-\nu\lambda_{xx})(x_j) and the right-hand side is −gj=−h(1+xj)-g_j=-h(1+x_j); had the residual been divided by the volume width, a density, the multiplier would be hλh\lambda, so check this convention before comparing). The unit scaling of the two constraint rows makes ψ0↔μ0\psi_0\leftrightarrow\mu_0 and ψN↔μ1\psi_N\leftrightarrow\mu_1, and the expectation is ψ0→νλx(0)\psi_0\to\nu\lambda_x(0), ψN→−νλx(1)\psi_N\to-\nu\lambda_x(1); the discrete and the continuous forms of the gradient then correspond term by term:

Dˉk=−∑j=1N−1ψj ∂Dk(Qj−Qj−1)⏟源项行 − ψ0 ∂Dkuin⏟入口 − ψN ∂Dkuout⏟出口 ⟷ −∫01λ ∂Dks dx − νλx(0) ∂Dkuin⏟入口 + νλx(1) ∂Dkuout⏟出口.\bar D_k=\underbrace{-\sum_{j=1}^{N-1}\psi_j\,\partial_{D_k}(Q_j-Q_{j-1})}_{\text{源项行}}\ \underbrace{-\,\psi_0\,\partial_{D_k}u_{\rm in}}_{\text{入口}}\ \underbrace{-\,\psi_N\,\partial_{D_k}u_{\rm out}}_{\text{出口}}\ \longleftrightarrow\ -\int_0^1\lambda\,\partial_{D_k}s\,\mathrm dx\ \underbrace{-\,\nu\lambda_x(0)\,\partial_{D_k}u_{\rm in}}_{\text{入口}}\ \underbrace{+\,\nu\lambda_x(1)\,\partial_{D_k}u_{\rm out}}_{\text{出口}}.
Dˉk=−∑j=1N−1ψj ∂Dk(Qj−Qj−1)⏟source rows − ψ0 ∂Dkuin⏟inlet − ψN ∂Dkuout⏟outlet ⟷ −∫01λ ∂Dks dx − νλx(0) ∂Dkuin⏟inlet + νλx(1) ∂Dkuout⏟outlet.\bar D_k=\underbrace{-\sum_{j=1}^{N-1}\psi_j\,\partial_{D_k}(Q_j-Q_{j-1})}_{\text{source rows}}\ \underbrace{-\,\psi_0\,\partial_{D_k}u_{\rm in}}_{\text{inlet}}\ \underbrace{-\,\psi_N\,\partial_{D_k}u_{\rm out}}_{\text{outlet}}\ \longleftrightarrow\ -\int_0^1\lambda\,\partial_{D_k}s\,\mathrm dx\ \underbrace{-\,\nu\lambda_x(0)\,\partial_{D_k}u_{\rm in}}_{\text{inlet}}\ \underbrace{+\,\nu\lambda_x(1)\,\partial_{D_k}u_{\rm out}}_{\text{outlet}}.

(对 k=2k=2 还有面通量里显含的 ν\nu 一项,见下面的“梯度误差的逐项分解”。)这里没有半个单元的因子,也没有格心页里半个单元上那种“入口值伴随”的换算:边界项就是乘子本身。这是由两个拉格朗日函数对照得到的预期,不是定理;下面逐项测量它,每一处都是数值证据。

(For k=2k=2 there is also the explicit ν\nu of the face flux, see “The gradient error, part by part” below.) There is no half-interval factor and no conversion like the “adjoint of the inlet value” of a half cell: the boundary term is the multiplier itself. This is what comparing the two Lagrangians leads one to expect, not a theorem; the rest of the section measures it, and every statement is numerical evidence.

“一致”在这里指什么,哪些只是证据

What “consistent” means here, and what is only evidence

本节说离散伴随与连续伴随一致,指的是固定设计、加密网格时测到四件事:(1) 内部节点上的逐点误差 max⁡1≤j≤N−1∣ψj−λ(xj)∣\max_{1\le j\le N-1}|\psi_j-\lambda(x_j)| 和 L1 范数 h∑j=1N−1∣ψj−λ(xj)∣h\sum_{j=1}^{N-1}|\psi_j-\lambda(x_j)| 趋于零;(2) 乘子 ψ0\psi_0、ψN\psi_N 趋于 νλx(0)\nu\lambda_x(0)、−νλx(1)-\nu\lambda_x(1);(3) 离散梯度 RDTψR_D^T\psi 趋于连续梯度;(4) 它的源项部分和两个边界部分分别趋于源项积分和边界项。本节的测量用模型算到 N=4096N=4096,用 Python 数据算到 N=16384N=16384(乘子到 N=65536N=65536)。这只是本问题上的数值证据,不是定理:本页不给出一般数据下的收敛定理。

In this section the discrete adjoint is called consistent with the continuous one when four things are measured at a fixed design under mesh refinement: (1) the pointwise error max⁡1≤j≤N−1∣ψj−λ(xj)∣\max_{1\le j\le N-1}|\psi_j-\lambda(x_j)| and the L1 norm h∑j=1N−1∣ψj−λ(xj)∣h\sum_{j=1}^{N-1}|\psi_j-\lambda(x_j)| at the interior nodes tend to zero; (2) the multipliers ψ0\psi_0, ψN\psi_N tend to νλx(0)\nu\lambda_x(0) and −νλx(1)-\nu\lambda_x(1); (3) the discrete gradient RDTψR_D^T\psi tends to the continuous gradient; (4) its source part and its two boundary parts tend to the source integral and the boundary term separately. The measurements go to N=4096N=4096 and to N=16384N=16384 with the Python data (the multipliers to N=65536N=65536). This is numerical evidence for this one problem, not a theorem: the page gives no convergence theorem for general data.

图 90 · 内部节点上的离散伴随 ψ_j(无限制器线性重构,N=8、32、128)与连续伴随 λ(x)(默认设计)。(a) 远离入口处,点离曲线很近(N=8 时第 2 到第 7 个节点上的误差至多 0.093);(b) 入口附近:λ 在宽约 ν/u_in 的层里从 0 降到 λ_out(0);x=0 处的紫圈不是 λ 的点值,而是乘子 ψ_0;尽管 N=8 时第一个内部节点 x_1 远在层外,它们仍落在虚线 νλ_x(0) 附近;(c) 误差 ψ_j-λ(x_j):到 N=128 为止最大值都在第 1 或第 2 个节点,N=8 时为 0.294,N=128 时为 0.036。λ(x)ψj​,N = 8ψj​,N = 32ψj​,N = 128乘子 ψ0​(紫圈,在 x = 0)−1.5−1−0.5000.20.40.60.81x伴随(a) 整个区间−1.5−1−0.5000.010.020.030.040.050.06x(b) 入口附近 x < 0.06ν λx​(0)ν/uin​−0.3−0.2−0.100.100.20.40.60.81xψj​ − λ(xj​)(c) 误差:最大值在第 1 或第 2 个节点(伴随的入口层所在处)
图 90 · 内部节点上的离散伴随 ψj\psi_j(无限制器线性重构,N=8N=8、32、128)与连续伴随 λ(x)\lambda(x)(默认设计)。(a) 远离入口处,点离曲线很近(N=8N=8 时第 2 到第 7 个节点上的误差至多 0.093);(b) 入口附近:λ\lambda 在宽约 ν/uin\nu/u_{\rm in} 的层里从 0 降到 λout(0)\lambda_{\rm out}(0);x=0x=0 处的紫圈不是 λ\lambda 的点值,而是乘子 ψ0\psi_0;尽管 N=8N=8 时第一个内部节点 x1x_1 远在层外,它们仍落在虚线 νλx(0)\nu\lambda_x(0) 附近;(c) 误差 ψj−λ(xj)\psi_j-\lambda(x_j):到 N=128N=128 为止最大值都在第 1 或第 2 个节点,N=8N=8 时为 0.294,N=128N=128 时为 0.036。
Figure 90 · The discrete adjoint ψ_j at the interior nodes (unlimited linear reconstruction, N=8, 32, 128) and the continuous adjoint λ(x) (default design). (a) Away from the inlet the points stay close to the curve (at N=8 the error at nodes 2 to 7 is at most 0.093); (b) near the inlet λ drops from 0 to λ_out(0) inside a layer of width about ν/u_in; the violet rings at x=0 are not point values of λ but the multipliers ψ_0, close to the dashed line νλ_x(0) although at N=8 the first interior node x_1 lies far outside the layer; (c) the error ψ_j-λ(x_j): up to N=128 its maximum is at node 1 or 2, 0.294 at N=8 and 0.036 at N=128.λ(x)ψj​, N = 8ψj​, N = 32ψj​, N = 128multiplier ψ0​ (violet rings, at x = 0)−1.5−1−0.5000.20.40.60.81xadjoint(a) the whole interval−1.5−1−0.5000.010.020.030.040.050.06x(b) near the inlet, x < 0.06ν λx​(0)ν/uin​−0.3−0.2−0.100.100.20.40.60.81xψj​ − λ(xj​)(c) the error: its maximum is at node 1 or 2, where the adjoint's inlet layer lies
Figure 90 · The discrete adjoint ψj\psi_j at the interior nodes (unlimited linear reconstruction, N=8N=8, 32, 128) and the continuous adjoint λ(x)\lambda(x) (default design). (a) Away from the inlet the points stay close to the curve (at N=8N=8 the error at nodes 2 to 7 is at most 0.093); (b) near the inlet λ\lambda drops from 0 to λout(0)\lambda_{\rm out}(0) inside a layer of width about ν/uin\nu/u_{\rm in}; the violet rings at x=0x=0 are not point values of λ\lambda but the multipliers ψ0\psi_0, close to the dashed line νλx(0)\nu\lambda_x(0) although at N=8N=8 the first interior node x1x_1 lies far outside the layer; (c) the error ψj−λ(xj)\psi_j-\lambda(x_j): up to N=128N=128 its maximum is at node 1 or 2, 0.294 at N=8N=8 and 0.036 at N=128N=128.

读图:N=8N=8 时 ψ1=−1.7095\psi_1=−1.7095,而 λ(x1)=−1.4158\lambda(x_1)=−1.4158;网格间距 h=0.125h=0.125 是伴随层宽的 11.4 倍,第一个内部节点根本“看不见”这个层,它的误差最大。但乘子 ψ0=−1.4061\psi_0=−1.4061 与 νλx(0)=−1.4266\nu\lambda_x(0)=−1.4266 只差 1.4%。换 NN、重构和设计,看误差的位置、大小和两个边界关系怎样变:

Reading the figure: at N=8N=8, ψ1=−1.7095\psi_1=−1.7095 while λ(x1)=−1.4158\lambda(x_1)=−1.4158; the interval h=0.125h=0.125 is 11.4 times the width of the adjoint's layer, the first interior node does not see the layer at all, and its error is the largest. Yet the multiplier ψ0=−1.4061\psi_0=−1.4061 differs from νλx(0)=−1.4266\nu\lambda_x(0)=−1.4266 by only 1.4%. Change NN, the reconstruction and the design in the panel below and watch where the error sits, how large it is and what the two boundary relations do:

加密:误差与收敛阶

Refinement: the errors and their orders

表中是内部节点上 ψj−λ(xj)\psi_j-\lambda(x_j) 的 L1 范数和最大值(模型算到 N=4096N=4096;最后一列是 Python 数据的 adjoint_l1_reference_error,它的 λ\lambda 由 SciPy 的 solve_bvp 独立求得;“阶”是相邻两层的观测阶 log⁡2(eN/2/eN)\log_2(e_{N/2}/e_N))。

The table lists the L1 norm and the maximum of ψj−λ(xj)\psi_j-\lambda(x_j) at the interior nodes (the model up to N=4096N=4096; the last column is the Python field adjoint_l1_reference_error, whose λ\lambda comes independently from SciPy's solve_bvp; “order” is the observed order log⁡2(eN/2/eN)\log_2(e_{N/2}/e_N) between neighbouring levels).

N一阶 L1first L1阶order一阶最大值first max无限制器 L1none L1阶order无限制器最大值none max光滑 L1smooth L1阶orderPython L1(无限制器)Python L1 (none)
81.06e−15.40e−19.12e−22.94e−11.11e−1—
166.42e−20.725.73e−15.09e−20.842.26e−17.45e−20.58—
324.52e−20.516.15e−12.12e−21.261.25e−12.37e−21.652.12e−2
642.73e−20.724.85e−17.66e−31.475.92e−29.47e−31.327.66e−3
1281.50e−20.873.05e−12.54e−31.593.64e−25.34e−30.822.54e−3
2567.85e−30.931.79e−18.00e−41.672.06e−23.72e−30.528.00e−4
5124.01e−30.979.79e−22.32e−41.798.00e−33.09e−30.272.32e−4
10242.03e−30.985.15e−26.26e−51.892.50e−31.84e−30.756.26e−5
20481.02e−30.992.64e−21.63e−51.956.97e−49.81e−40.911.63e−5
40965.11e−41.001.34e−24.14e−61.971.84e−45.02e−40.974.14e−6
8192—————1.04e−6
16384—————2.62e−7
图 91 · ψ_j-λ(x_j) 随网格加密(默认设计)。实线 L1、虚线最大值;圆圈是 Python 数据(无限制器)。紫色竖线是 h=ν/u_in:竖线左侧的网格分辨不出伴随的这个层。最细两层之间的阶:无限制器 L1 1.97、最大值 1.92;一阶 1.00 与 0.98;光滑限制器 L1 0.97。一阶最大值一阶 L1无限制器最大值无限制器 L1光滑 L1Python 数据 L1(无限制器)10-7​10-6​10-5​10-4​10-3​10-2​10-1​110102​103​104​区间数 N|ψj​ − λ(xj​)| 的范数h = ν/uin​hh2​
图 91 · ψj−λ(xj)\psi_j-\lambda(x_j) 随网格加密(默认设计)。实线 L1、虚线最大值;圆圈是 Python 数据(无限制器)。紫色竖线是 h=ν/uinh=\nu/u_{\rm in}:竖线左侧的网格分辨不出伴随的这个层。最细两层之间的阶:无限制器 L1 1.97、最大值 1.92;一阶 1.00 与 0.98;光滑限制器 L1 0.97。
Figure 91 · ψ_j-λ(x_j) under mesh refinement (default design). Solid: L1, dashed: maximum; rings: the Python data (unlimited linear). The violet line marks h=ν/u_in: the meshes to its left do not resolve the adjoint's layer. Orders between the two finest levels: unlimited linear L1 1.97, maximum 1.92; first order 1.00 and 0.98; smooth limiter L1 0.97.first maxfirst L1none maxnone L1smooth L1Python data L1 (none)10-7​10-6​10-5​10-4​10-3​10-2​10-1​110102​103​104​intervals Nnorm of ψj​ − λ(xj​)h = ν/uin​hh2​
Figure 91 · ψj−λ(xj)\psi_j-\lambda(x_j) under mesh refinement (default design). Solid: L1, dashed: maximum; rings: the Python data (unlimited linear). The violet line marks h=ν/uinh=\nu/u_{\rm in}: the meshes to its left do not resolve the adjoint's layer. Orders between the two finest levels: unlimited linear L1 1.97, maximum 1.92; first order 1.00 and 0.98; smooth limiter L1 0.97.

结论(测量):无限制器线性的离散伴随二阶收敛到连续伴随,一阶格式一阶收敛,最大误差和 L1 误差同阶。光滑限制器的 ϵ=0.01\epsilon=0.01 固定,网格足够细(h∣ux∗∣≪ϵh|u^*_x|\ll\epsilon)后限制器几乎关闭,这时内部面的迹之差已和一阶格式相同:N=4096N=4096 时 (qR−qL)/(h ux∗)(q_R-q_L)/(h\,u^*_x) 在靠近两端的内部面上是 0.9985(全部内部面上介于 0.9981 与 1.0000 之间;一阶格式为 1.0000),所以它的收敛阶也降到一阶:N=32N=32 时 L1 的观测阶是 1.65,N=512N=512 时只有 0.27,N=4096N=4096 时为 0.97。粗网格上无限制器线性的最大误差总在第 1 或第 2 个内部节点(伴随的入口层所在处):N=8N=8 时 0.294,N=16N=16 时 0.226,N=64N=64 时 0.059;这些网格都分辨不出伴随的层(N<uin/ν≈91N<u_{\rm in}/\nu\approx91)。作对比,格心页同一设计、N=8N=8 时最大误差是 0.554,L1 误差 0.125(本页 0.091);N=4096N=4096 时 L1 误差分别为 1.03e−5(格心页)与 4.14e−6(本页)。

Conclusion (measured): for unlimited linear reconstruction the discrete adjoint converges to the continuous one at second order, for the first-order scheme at first order, with the same order in the maximum and in the L1 norm. The smooth limiter has a fixed ϵ=0.01\epsilon=0.01; once the mesh is fine enough (h∣ux∗∣≪ϵh|u^*_x|\ll\epsilon) the limiter is nearly off and the jump of the traces at an interior face is that of the first-order scheme: at N=4096N=4096 the ratio (qR−qL)/(h ux∗)(q_R-q_L)/(h\,u^*_x) is 0.9985 on the interior faces next to the ends (between 0.9981 and 1.0000 over all interior faces; 1.0000 for the first-order scheme), so its order also falls to one: the observed L1 order is 1.65 at N=32N=32, only 0.27 at N=512N=512 and 0.97 at N=4096N=4096. On coarse meshes the maximum error of unlimited linear reconstruction is always at the first or second interior node, where the adjoint's inlet layer lies: 0.294 at N=8N=8, 0.226 at N=16N=16 and 0.059 at N=64N=64; none of these meshes resolves the adjoint's layer (N<uin/ν≈91N<u_{\rm in}/\nu\approx91). For comparison, on the cell-centred page the same design gives a maximum error of 0.554 and an L1 error of 0.125 at N=8N=8 (this page: 0.091), and L1 errors of 1.03e−5 and 4.14e−6 at N=4096N=4096.

核心结果:入口与出口约束行的乘子

The central result: the multipliers of the inlet and outlet constraint rows

乘子 ψ0\psi_0 不是额外要解的未知量,它由伴随方程的第 0 行决定:AA 的第 0 行是单位行,第 0 列只在约束行本身和读到 U0U_0 的面所在的行里有非零元。于是 ATψ=−gA^T\psi=-g 的第 0 行是 ψ0+∑i≥1Ai0ψi=−w0\psi_0+\sum_{i\ge1}A_{i0}\psi_i=-w_0,其中 w0=h/2w_0=h/2。把 Ai0A_{i0} 写成读到 U0U_0 的那些面通量的导数。分发的转置给出:通量和 ∑fHf Ψf\sum_fH_f\,\Psi_f 里的系数是 Ψf=ψ~f−ψ~f+1\Psi_f=\tilde\psi_f-\tilde\psi_{f+1},其中 ψ~=(0,ψ1,…,ψN−1,0)\tilde\psi=(0,\psi_1,\dots,\psi_{N-1},0):通量和看到的是两端补零的 ψ\psi,正是连续伴随的边界条件 λ(0)=λ(1)=0\lambda(0)=\lambda(1)=0。所以

The multiplier ψ0\psi_0 is not an extra unknown to be solved for: it is fixed by row 0 of the adjoint equation. Row 0 of AA is the unit row, and column 0 has nonzeros only in that row and in the rows of the faces that read U0U_0. So row 0 of ATψ=−gA^T\psi=-g is ψ0+∑i≥1Ai0ψi=−w0\psi_0+\sum_{i\ge1}A_{i0}\psi_i=-w_0, with w0=h/2w_0=h/2. Write Ai0A_{i0} through the derivatives of the face fluxes that read U0U_0. The transposed scatter gives the coefficients of the flux sum ∑fHf Ψf\sum_fH_f\,\Psi_f as Ψf=ψ~f−ψ~f+1\Psi_f=\tilde\psi_f-\tilde\psi_{f+1} with ψ~=(0,ψ1,…,ψN−1,0)\tilde\psi=(0,\psi_1,\dots,\psi_{N-1},0): the flux sum sees ψ\psi extended by zero at both ends, which is the boundary condition λ(0)=λ(1)=0\lambda(0)=\lambda(1)=0 of the continuous adjoint. Hence

ψ0=−w0−∑f∂Hf∂U0 Ψf=−h2+∂H0∂U0 ψ1−∂H1∂U0 (ψ1−ψ2),∂H0∂U0=νh⏟黏性+(cL∂qL∂U0+cR∂qR∂U0)面 0,\psi_0=-w_0-\sum_f\frac{\partial H_f}{\partial U_0}\,\Psi_f=-\frac h2+\frac{\partial H_0}{\partial U_0}\,\psi_1-\frac{\partial H_1}{\partial U_0}\,(\psi_1-\psi_2),\qquad \frac{\partial H_0}{\partial U_0}=\underbrace{\frac\nu h}_{\text{黏性}}+\bigl(c_L\tfrac{\partial q_L}{\partial U_0}+c_R\tfrac{\partial q_R}{\partial U_0}\bigr)_{\text{面 }0},
ψ0=−w0−∑f∂Hf∂U0 Ψf=−h2+∂H0∂U0 ψ1−∂H1∂U0 (ψ1−ψ2),∂H0∂U0=νh⏟viscous+(cL∂qL∂U0+cR∂qR∂U0)face 0,\psi_0=-w_0-\sum_f\frac{\partial H_f}{\partial U_0}\,\Psi_f=-\frac h2+\frac{\partial H_0}{\partial U_0}\,\psi_1-\frac{\partial H_1}{\partial U_0}\,(\psi_1-\psi_2),\qquad \frac{\partial H_0}{\partial U_0}=\underbrace{\frac\nu h}_{\text{viscous}}+\bigl(c_L\tfrac{\partial q_L}{\partial U_0}+c_R\tfrac{\partial q_R}{\partial U_0}\bigr)_{\text{face }0},

(第三项只在二阶格式里出现:面 1 通过节点 1 的斜率读到 U0U_0。)黏性部分是 ν ψ1/h=ν (ψ1−0)/h\nu\,\psi_1/h=\nu\,(\psi_1-0)/h:ν\nu 乘以 ψ\psi 在入口处的单侧差商,也就是离散的 νλx(0)\nu\lambda_x(0)。其余是面 0 的对流通量与 Rusanov 耗散。一阶格式只有面 0 读到 U0U_0(qL=U0q_L=U_0,cL=uin/2+1c_L=u_{\rm in}/2+1),给出封闭形式;在出口,同样的论证给出 ψN\psi_N:

(The third term occurs only in the second-order schemes: face 1 reads U0U_0 through the slope of node 1.) The viscous part is ν ψ1/h=ν (ψ1−0)/h\nu\,\psi_1/h=\nu\,(\psi_1-0)/h: ν\nu times the one-sided difference quotient of ψ\psi at the inlet, the discrete νλx(0)\nu\lambda_x(0). The rest is the convective flux and the Rusanov dissipation of face 0. The first-order scheme has only face 0 reading U0U_0 (qL=U0q_L=U_0, cL=uin/2+1c_L=u_{\rm in}/2+1), which gives closed forms; at the outlet the same argument gives ψN\psi_N:

一阶:ψ0=(1+νh+uin2)ψ1−h2,ψN=(1+νh−uout2)ψN−1−h.\text{一阶:}\qquad \psi_0=\Bigl(1+\frac\nu h+\frac{u_{\rm in}}2\Bigr)\psi_1-\frac h2,\qquad \psi_N=\Bigl(1+\frac\nu h-\frac{u_{\rm out}}2\Bigr)\psi_{N-1}-h.
first order:ψ0=(1+νh+uin2)ψ1−h2,ψN=(1+νh−uout2)ψN−1−h.\text{first order:}\qquad \psi_0=\Bigl(1+\frac\nu h+\frac{u_{\rm in}}2\Bigr)\psi_1-\frac h2,\qquad \psi_N=\Bigl(1+\frac\nu h-\frac{u_{\rm out}}2\Bigr)\psi_{N-1}-h.

这两个等式是代数恒等式:本页在 N=8N=8、32、128 的收敛解上核对,相差不超过 10−1410^{-14}。测量乘子与连续边界通量的关系(无限制器线性,默认设计;“黏性部分”是 νψ1/h\nu\psi_1/h):

These two equalities are algebraic identities: this page checks them on the converged states at N=8N=8, 32 and 128, to within 10−1410^{-14}. The measured relation of the multiplier to the continuous boundary flux (unlimited linear, default design; the “viscous part” is νψ1/h\nu\psi_1/h):

Nψ0\psi_0ψ0÷νλx(0)\psi_0\div\nu\lambda_x(0)ψ0÷νλx(0)\psi_0\div\nu\lambda_x(0)黏性部分 νψ1/h\nu\psi_1/hviscous part νψ1/h\nu\psi_1/h黏性部分占 ψ0\psi_0 的百分比its share of ψ0\psi_0 (%)斜率比 (ψ1/h)÷λx(0)(\psi_1/h)\div\lambda_x(0)slope ratio (ψ1/h)÷λx(0)(\psi_1/h)\div\lambda_x(0)
8−1.40610.9856−0.13689.70.096
16−1.40120.9822−0.272719.50.191
32−1.41360.9909−0.493934.90.346
64−1.42120.9963−0.783255.10.549
128−1.42470.9987−1.061874.50.744
256−1.42600.9996−1.250187.70.876
512−1.42640.9999−1.346394.40.944
1024−1.42651.0000−1.389897.40.974
2048−1.42661.0000−1.409298.80.988
4096−1.42661.0000−1.418299.40.994

N=8N=8 时 ψ0\psi_0 与 νλx(0)\nu\lambda_x(0) 只差 1.4%,而斜率 ψ1/h\psi_1/h 只再现了 λx(0)\lambda_x(0) 的 9.6%,黏性部分只占 ψ0\psi_0 的 9.7%:这时的乘子几乎全由面 0、面 1 的对流通量和 Rusanov 耗散承担,网格根本分辨不了层,但(在默认设计下)第一个控制体的通量收支是对的。斜率要到 N=512N=512 才进入 10% 以内(一阶格式要到 N=2048N=2048),黏性部分在 N=2048N=2048 时占 98.8%,在 N=4096N=4096 时占 99.4%。这是默认设计下的观测,不是对所有设计都成立的规律:a=−0.5a=−0.5、φ=0.25\varphi=0.25(uin=1.5u_{\rm in}=1.5,ν\nu 不变)时 N=8N=8 的乘子比是 2.35,N=16N=16 和 32 时是 1.06 和 1.01(上面的面板可以试别的设计)。下面的渐近分析给出一种启发式的读法(不是被分离出来的原因):νλx(0)≈uinλout(0)\nu\lambda_x(0)\approx u_{\rm in}\lambda_{\rm out}(0) 是外解的性质——层两侧的跳跃乘以 uinu_{\rm in},与黏性无关——所以通量收支里的对流部分把外解的值带对时,乘子就对,不必分辨层本身;最粗的网格上是否如此取决于设计。

At N=8N=8 the multiplier ψ0\psi_0 differs from νλx(0)\nu\lambda_x(0) by only 1.4%, while the slope ψ1/h\psi_1/h reproduces only 9.6% of λx(0)\lambda_x(0) and the viscous part is only 9.7% of ψ0\psi_0: the multiplier is carried almost entirely by the convective flux and the Rusanov dissipation of faces 0 and 1. The mesh cannot resolve the layer, but (at the default design) the flux balance of the first volume is right. The slope comes within 10% only at N=512N=512 (the first-order scheme needs N=2048N=2048), and the viscous part is 98.8% of ψ0\psi_0 at N=2048N=2048 and 99.4% at N=4096N=4096. This is an observation at the default design, not a rule for every design: for a=−0.5a=−0.5, φ=0.25\varphi=0.25 (uin=1.5u_{\rm in}=1.5, same ν\nu) the multiplier ratio is 2.35 at N=8N=8, and 1.06 and 1.01 at N=16N=16 and 32 (the panel above lets you try other designs). The asymptotics below give a heuristic reading (not an isolated cause): νλx(0)≈uinλout(0)\nu\lambda_x(0)\approx u_{\rm in}\lambda_{\rm out}(0) is a property of the outer solution, the jump across the layer times uinu_{\rm in}, independent of the viscosity, so when the convective part of the flux balance carries the value of the outer solution correctly the multiplier comes out right without resolving the layer; whether it does so on the coarsest mesh depends on the design.

误差与阶:下表比较两个乘子在一阶和无限制器线性格式下的误差(—:这两个网格上带符号的误差变号,不给出阶)。ψN\psi_N 的绝对误差同样收敛,但 −νλx(1)=−0.0220-\nu\lambda_x(1)=−0.0220 很小,所以粗网格上的相对误差很大:N=8N=8 时 ψN=−0.0870\psi_N=−0.0870,是连续值的 3.95 倍。无限制器线性时两个乘子的误差从 N=32N=32 起大小相等、符号相反:e0+eNe_0+e_N 只有 e0e_0 的 0.004 倍(N=64N=64)到 0.011 倍(N=4096N=4096);一阶格式的两个误差从 N=16N=16 起同号(N=4096N=4096 时 e0+eN=2.31 e0e_0+e_N=2.31\,e_0)。因为 uin=uoutu_{\rm in}=u_{\rm out},梯度的 aa、φ\varphi 分量只通过两个乘子之和 ψ0+ψN\psi_0+\psi_N 看到它们。

The errors and orders: the table compares the two multipliers under the first-order and unlimited linear schemes (—: the signed error changes sign between the two meshes, so no order is printed). The absolute error of ψN\psi_N converges too, but −νλx(1)=−0.0220-\nu\lambda_x(1)=−0.0220 is small, so on coarse meshes the relative error is large: at N=8N=8, ψN=−0.0870\psi_N=−0.0870 is 3.95 times the continuous value. For unlimited linear the two errors are equal and opposite from N=32N=32 on: e0+eNe_0+e_N is only 0.004 of e0e_0 at N=64N=64 and 0.011 at N=4096N=4096; for the first-order scheme the two errors have the same sign from N=16N=16 on (e0+eN=2.31 e0e_0+e_N=2.31\,e_0 at N=4096N=4096). Since uin=uoutu_{\rm in}=u_{\rm out}, the aa and φ\varphi components of the gradient see the two multipliers only through their sum ψ0+ψN\psi_0+\psi_N.

N一阶 ∣ψ0−νλx(0)∣|\psi_0-\nu\lambda_x(0)|first ∣ψ0−νλx(0)∣|\psi_0-\nu\lambda_x(0)|阶order无限制器 ∣ψ0−νλx(0)∣|\psi_0-\nu\lambda_x(0)|none ∣ψ0−νλx(0)∣|\psi_0-\nu\lambda_x(0)|阶order一阶 ∣ψN+νλx(1)∣|\psi_N+\nu\lambda_x(1)|first ∣ψN+νλx(1)∣|\psi_N+\nu\lambda_x(1)|阶order无限制器 ∣ψN+νλx(1)∣|\psi_N+\nu\lambda_x(1)|none ∣ψN+νλx(1)∣|\psi_N+\nu\lambda_x(1)|阶order
81.7e−22.0e−22.8e−16.5e−2
166.9e−2—2.5e−2−0.311.4e−10.973.0e−21.14
324.8e−20.531.3e−20.977.1e−21.011.3e−21.17
642.6e−20.885.3e−31.283.5e−21.015.3e−31.31
1281.3e−20.971.9e−31.511.7e−21.011.9e−31.51
2566.6e−30.995.8e−41.708.7e−31.005.7e−41.71
5123.3e−31.001.6e−41.854.3e−31.001.6e−41.85
10241.7e−31.004.2e−51.922.2e−31.004.2e−51.93
20488.3e−41.001.1e−51.961.1e−31.001.1e−51.96
40964.1e−41.002.7e−61.985.4e−41.002.7e−61.98
图 92 · 两个乘子随 N 的变化(默认设计)。(a) 实线:ψ_0νλ_x(0),从 N=8 起就在 1 附近(无限制器 0.986,一阶 0.988,光滑 0.946);虚线:斜率 ψ_1/h 与 λ_x(0) 之比,要到远在紫线右侧(h ≪ ν/u_in,N 上千)才接近 1;圆圈:Python 数据的乘子之比。(b) 乘子的绝对误差,实线 ψ_0、虚线 ψ_N:无限制器线性二阶,一阶格式一阶。ψ0​ ÷ (ν λx​(0))(一阶)ψ0​ ÷ (ν λx​(0))(无限制器)ψ0​ ÷ (ν λx​(0))(光滑)(ψ1​/h) ÷ λx​(0)(一阶)(ψ1​/h) ÷ λx​(0)(无限制器)Python 数据:ψ0​ ÷ (ν λx​(0))00.20.40.60.811.110102​103​104​区间数 N与连续值之比h = ν/uin​|ψ0​ − ν λx​(0)|(一阶)|ψ0​ − ν λx​(0)|(无限制器)|ψN​ + ν λx​(1)|(一阶)|ψN​ + ν λx​(1)|(无限制器)Python 数据:|ψ0​ − ν λx​(0)|10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​110102​103​104​区间数 N乘子的误差hh2​
图 92 · 两个乘子随 NN 的变化(默认设计)。(a) 实线:ψ0÷νλx(0)\psi_0\div\nu\lambda_x(0),从 N=8N=8 起就在 1 附近(无限制器 0.986,一阶 0.988,光滑 0.946);虚线:斜率 ψ1/h\psi_1/h 与 λx(0)\lambda_x(0) 之比,要到远在紫线右侧(h≪ν/uinh\ll\nu/u_{\rm in},NN 上千)才接近 1;圆圈:Python 数据的乘子之比。(b) 乘子的绝对误差,实线 ψ0\psi_0、虚线 ψN\psi_N:无限制器线性二阶,一阶格式一阶。
Figure 92 · The two multipliers against N (default design). (a) Solid: ψ_0νλ_x(0), close to 1 from N=8 on (0.986 unlimited linear, 0.988 first order, 0.946 smooth); dashed: the slope ψ_1/h over λ_x(0), which approaches 1 only well to the right of the violet line (h ≪ ν/u_in, N in the thousands); rings: the multiplier ratio of the Python data. (b) The absolute errors of the multipliers, solid ψ_0, dashed ψ_N: second order for unlimited linear, first order for the first-order scheme.first: ψ0​ ÷ (ν λx​(0))none: ψ0​ ÷ (ν λx​(0))smooth: ψ0​ ÷ (ν λx​(0))first: (ψ1​/h) ÷ λx​(0)none: (ψ1​/h) ÷ λx​(0)Python data: ψ0​ ÷ (ν λx​(0))00.20.40.60.811.110102​103​104​intervals Nratio to the continuous valueh = ν/uin​first: |ψ0​ − ν λx​(0)|none: |ψ0​ − ν λx​(0)|first: |ψN​ + ν λx​(1)|none: |ψN​ + ν λx​(1)|Python data: |ψ0​ − ν λx​(0)|10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​110102​103​104​intervals Nerror of the multiplierhh2​
Figure 92 · The two multipliers against NN (default design). (a) Solid: ψ0÷νλx(0)\psi_0\div\nu\lambda_x(0), close to 1 from N=8N=8 on (0.986 unlimited linear, 0.988 first order, 0.946 smooth); dashed: the slope ψ1/h\psi_1/h over λx(0)\lambda_x(0), which approaches 1 only well to the right of the violet line (h≪ν/uinh\ll\nu/u_{\rm in}, NN in the thousands); rings: the multiplier ratio of the Python data. (b) The absolute errors of the multipliers, solid ψ0\psi_0, dashed ψN\psi_N: second order for unlimited linear, first order for the first-order scheme.

ψ0→νλx(0)\psi_0\to\nu\lambda_x(0) 是单位缩放的约束行的性质。若把约束行乘以 cc(R0=c (U0−uin)R_0=c\,(U_0-u_{\rm in}),解、JhJ_h、ψ1,…,ψN−1\psi_1,\dots,\psi_{N-1} 和梯度都不变),则 ψ0\psi_0 变为 ψ0/c\psi_0/c:N=16N=16、c=1/hc=1/h 时 ψ0=−1.4012\psi_0=−1.4012 变成 ψ0=−0.0876\psi_0=−0.0876。比较乘子与 νλx(0)\nu\lambda_x(0) 之前先确认约束行的缩放;梯度公式里 ψ0\psi_0 乘的是 R0R_0 对设计的导数,缩放互相抵消。

ψ0→νλx(0)\psi_0\to\nu\lambda_x(0) is a property of the unit-scaled constraint row. If the row is multiplied by cc (R0=c (U0−uin)R_0=c\,(U_0-u_{\rm in}); the solution, JhJ_h, ψ1,…,ψN−1\psi_1,\dots,\psi_{N-1} and the gradient do not change), then ψ0\psi_0 becomes ψ0/c\psi_0/c: at N=16N=16 with c=1/hc=1/h, ψ0=−1.4012\psi_0=−1.4012 becomes ψ0=−0.0876\psi_0=−0.0876. Check the scaling of the constraint rows before comparing a multiplier with νλx(0)\nu\lambda_x(0); in the gradient formula ψ0\psi_0 multiplies the derivative of R0R_0 with respect to the design, and the scalings cancel.

边界面为什么重要:不取边界斜率的实验

Why the boundary faces matter: an experiment without boundary slopes

边界节点用单侧斜率 σ0=r0\sigma_0=r_0、σN=lN\sigma_N=l_N(第 3 节),所以边界面的迹也有二阶精度。若不给边界节点斜率(σ0=σN=0\sigma_0=\sigma_N=0,其他一切不变;这只是实验,不是本页的格式),两个边界面就只有一阶精度的迹——这正是格心页那两个不重构的端单元的情形。这里用同一段代码(切线、反向、复数语句都写出并通过点积检验和复数步长)看伴随和梯度:网格分辨伴随层的能力没变,误差却大幅上升:

The boundary nodes use the one-sided slopes σ0=r0\sigma_0=r_0, σN=lN\sigma_N=l_N (Section 3), so the traces of the boundary faces are second-order accurate too. Without a slope at the boundary nodes (σ0=σN=0\sigma_0=\sigma_N=0, everything else unchanged; an experiment only, not the page's scheme) the two boundary faces have first-order traces, which is the situation of the two unreconstructed end cells of the cell-centred page. Here the same code (tangent, reverse and complex statements all written out and passed through the dot test and complex step) is used for the adjoint and the gradient: the mesh resolves the adjoint's layer no better than before, but the errors rise sharply:

Nmax⁡∣ψ−λ∣\max|\psi-\lambda|(本页)max⁡∣ψ−λ∣\max|\psi-\lambda| (page)max⁡∣ψ−λ∣\max|\psi-\lambda|(无边界斜率)max⁡∣ψ−λ∣\max|\psi-\lambda| (no boundary slope)aa 梯度误差(本页)aa-gradient error (page)aa 梯度误差(无边界斜率)aa-gradient error (no boundary slope)ψ0÷νλx(0)\psi_0\div\nu\lambda_x(0)(本页)ψ0÷νλx(0)\psi_0\div\nu\lambda_x(0) (page)ψ0÷νλx(0)\psi_0\div\nu\lambda_x(0)(无边界斜率)ψ0÷νλx(0)\psi_0\div\nu\lambda_x(0) (no boundary slope)
80.2940.3213.41e−26.71e−10.98561.0471
160.2260.4191.39e−22.91e−10.98221.0159
320.1250.4625.33e−31.28e−10.99091.0054
640.0590.3551.18e−35.27e−20.99631.0015

没有边界斜率时,aa 分量的梯度误差(绝对值)在 N=8N=8 时从 0.034 升到 0.671,N=64N=64 时从 1.2×10−31.2\times10^{-3} 升到 5.3×10−25.3\times10^{-2};格心页在 N=8N=8 时的 aa 分量梯度误差是 0.343。渐近地它仍是二阶(最细两层之间状态误差的阶 1.97),但中间过渡很长:N=16N=16 到 1024 之间的阶只有 1.15 到 1.88,N=4096N=4096 时状态误差仍是本页的 123 倍。所以格点格式在粗网格上 aa 分量梯度误差的优势(N=8N=8:0.034 对 0.343)主要来自边界面的二阶迹:格心页把端单元重构之后也只有 0.030。这是对两个实验的直接比较,对 φ\varphi 分量(格点格式更差)和两种格式的其余差别什么也没有说。

Without the boundary slopes the aa-gradient error (absolute value) rises from 0.034 to 0.671 at N=8N=8 and from 1.2×10−31.2\times10^{-3} to 5.3×10−25.3\times10^{-2} at N=64N=64; on the cell-centred page the aa-gradient error at N=8N=8 is 0.343. Asymptotically it is still second order (state-error order 1.97 between the two finest levels) but the transient is long: between N=16N=16 and 1024 the orders are only 1.15 to 1.88, and at N=4096N=4096 the state error is still 123 times the page's. So the advantage of the node scheme in the aa-gradient error on coarse meshes (0.034 against 0.343 at N=8N=8) comes mainly from the second-order traces of its boundary faces: the cell page, once its end cells are reconstructed, reaches 0.030. This compares two experiments directly; it says nothing about the φ\varphi component (worse on the node scheme) or about the other differences between the schemes.

图 93 · 边界节点的斜率实验(无限制器线性,默认设计)。(a) N=8 时入口附近的 ψ_j:本页格式(圆圈)与边界节点不取斜率(实心点)。(b) 两者的 a 分量梯度误差(实线)和状态 L1 误差(虚线):紫线左侧的网格(N ≤ 64)都分辨不出伴随的层,去掉边界斜率后梯度误差仍是本页的 19 倍以上。λ(x)本页格式(边界节点有单侧斜率)实验:边界节点不取斜率−1.5−1−0.5000.10.20.30.40.5x伴随(a) N = 8,入口附近10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​1101001000N误差h = ν/uin​(b) 实线 |dJh​/da − dJ/da|,虚线 状态 L1h2​
图 93 · 边界节点的斜率实验(无限制器线性,默认设计)。(a) N=8N=8 时入口附近的 ψj\psi_j:本页格式(圆圈)与边界节点不取斜率(实心点)。(b) 两者的 aa 分量梯度误差(实线)和状态 L1 误差(虚线):紫线左侧的网格(N≤64N\le64)都分辨不出伴随的层,去掉边界斜率后梯度误差仍是本页的 19 倍以上。
Figure 93 · The boundary-slope experiment (unlimited linear, default design). (a) ψ_j near the inlet at N=8: the page (rings) and the boundary nodes without a slope (dots). (b) The a-gradient error (solid) and the state L1 error (dashed) of the two: no mesh left of the violet line (N ≤ 64) resolves the adjoint's layer, and without the boundary slopes the gradient error is still more than 19 times larger.λ(x)the page (one-sided slope at the boundary nodes)experiment: no slope at the boundary nodes−1.5−1−0.5000.10.20.30.40.5xadjoint(a) N = 8, near the inlet10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​1101001000Nerrorh = ν/uin​(b) solid |dJh​/da − dJ/da|, dashed state L1h2​
Figure 93 · The boundary-slope experiment (unlimited linear, default design). (a) ψj\psi_j near the inlet at N=8N=8: the page (rings) and the boundary nodes without a slope (dots). (b) The aa-gradient error (solid) and the state L1 error (dashed) of the two: no mesh left of the violet line (N≤64N\le64) resolves the adjoint's layer, and without the boundary slopes the gradient error is still more than 19 times larger.

播放器逐层演示加密过程,可以在本页格式、没有边界斜率的实验和本节最后要讲的错误版本之间切换:

The player shows the refinement level by level; it switches between the page's scheme, the experiment without boundary slopes and the wrong version of the last part of this section:

一阶格式就是黏性为 ν + h 的中心格式

First order is the central scheme with viscosity ν + h

为什么一阶离散伴随的层那么宽?看一阶格式(σj=0\sigma_j=0,qL=Ufq_L=U_f,qR=Uf+1q_R=U_{f+1})。格点格式里每一个内部行 1≤j≤N−11\le j\le N-1 的两个面都是普通面(df=hd_f=h,边界面也一样),代入第 3 节的通量:

Why is the layer of the first-order discrete adjoint so wide? Take the first-order scheme (σj=0\sigma_j=0, qL=Ufq_L=U_f, qR=Uf+1q_R=U_{f+1}). On the node-centred mesh every interior row 1≤j≤N−11\le j\le N-1 has two ordinary faces (df=hd_f=h, the boundary faces included); insert the flux of Section 3:

Hj−Hj−1=14(Uj2+Uj+12)−(Uj+1−Uj)−νh(Uj+1−Uj)−14(Uj−12+Uj2)+(Uj−Uj−1)+νh(Uj−Uj−1).H_j-H_{j-1}=\tfrac14\bigl(U_j^2+U_{j+1}^2\bigr)-(U_{j+1}-U_j)-\tfrac{\nu}{h}(U_{j+1}-U_j)-\tfrac14\bigl(U_{j-1}^2+U_j^2\bigr)+(U_j-U_{j-1})+\tfrac{\nu}{h}(U_j-U_{j-1}).

Uj2U_j^2 抵消,两个跳跃合成一个二阶差分,耗散与黏性合并:

The Uj2U_j^2 terms cancel, the two jumps combine into one second difference, and the dissipation joins the viscosity:

Rj=Uj+12−Uj−124−(1+νh)(Uj+1−2Uj+Uj−1)−(Qj−Qj−1)=h[12Uj+12−12Uj−122h−(ν+h) Uj+1−2Uj+Uj−1h2]−(Qj−Qj−1).R_j=\frac{U_{j+1}^2-U_{j-1}^2}{4}-\Bigl(1+\frac{\nu}{h}\Bigr)\bigl(U_{j+1}-2U_j+U_{j-1}\bigr)-(Q_j-Q_{j-1})=h\Bigl[\frac{\tfrac12U_{j+1}^2-\tfrac12U_{j-1}^2}{2h}-(\nu+h)\,\frac{U_{j+1}-2U_j+U_{j-1}}{h^2}\Bigr]-(Q_j-Q_{j-1}).

方括号正是 u ux−(ν+h) uxxu\,u_x-(\nu+h)\,u_{xx} 的中心差分:Rusanov 耗散系数 α/2=1\alpha/2=1 相当于额外黏性 hh(即 αh/2\alpha h/2)。再看转置:第 jj 列在行 j−1,j,j+1j-1,j,j+1 里有三个非零元;约束行(第 0 行和第 NN 行)里 A01=AN,N−1=0A_{01}=A_{N,N-1}=0,所以伴随方程的行 1≤j≤N−11\le j\le N-1 是

The bracket is exactly the central difference of u ux−(ν+h) uxxu\,u_x-(\nu+h)\,u_{xx}: the Rusanov dissipation coefficient α/2=1\alpha/2=1 acts as an added viscosity hh (that is αh/2\alpha h/2). Now transpose: column jj has three nonzero entries in rows j−1,j,j+1j-1,j,j+1; in the constraint rows (rows 0 and NN) A01=AN,N−1=0A_{01}=A_{N,N-1}=0, so the rows 1≤j≤N−11\le j\le N-1 of the adjoint equation are

(ATψ)j=−Uj ψ~j+1−ψ~j−12−(1+νh)(ψ~j+1−2ψ~j+ψ~j−1)=h[−Uj ψ~j+1−ψ~j−12h−(ν+h) ψ~j+1−2ψ~j+ψ~j−1h2]=−h (1+xj),ψ~0=ψ~N=0.(A^T\psi)_j=-U_j\,\frac{\tilde\psi_{j+1}-\tilde\psi_{j-1}}{2}-\Bigl(1+\frac\nu h\Bigr)\bigl(\tilde\psi_{j+1}-2\tilde\psi_j+\tilde\psi_{j-1}\bigr)=h\Bigl[-U_j\,\frac{\tilde\psi_{j+1}-\tilde\psi_{j-1}}{2h}-(\nu+h)\,\frac{\tilde\psi_{j+1}-2\tilde\psi_j+\tilde\psi_{j-1}}{h^2}\Bigr]=-h\,(1+x_j),\qquad \tilde\psi_0=\tilde\psi_N=0.

除以 hh:一阶离散伴随的全部内部各行,正是黏性为 ν+h\nu+h、边界值为零的连续伴随 −uλx−(ν+h)λxx=−(1+x)-u\lambda_x-(\nu+h)\lambda_{xx}=-(1+x),λ(0)=λ(1)=0\lambda(0)=\lambda(1)=0 的中心格式(对流系数取离散状态 UjU_j);两个乘子随后由第 0 行和第 NN 行读出,即上面的封闭形式。这是恒等式,不是近似:Python 审计用 sympy 符号化简验证,本页在收敛解上逐行核对,差不超过 10−1410^{-14}。所以一阶离散伴随的层宽约 (ν+h)/uin(\nu+h)/u_{\rm in} 而不是 ν/uin\nu/u_{\rm in}:N=8N=8 时前者是后者的 13.5 倍。格心页里这个恒等式在两个端行失效(边界面距离 h/2h/2);这里没有例外。

Divide by hh: all interior rows of the first-order discrete adjoint are the central scheme for the continuous adjoint with viscosity ν+h\nu+h and zero boundary values, −uλx−(ν+h)λxx=−(1+x)-u\lambda_x-(\nu+h)\lambda_{xx}=-(1+x), λ(0)=λ(1)=0\lambda(0)=\lambda(1)=0 (with the discrete state UjU_j as the convection coefficient); the two multipliers are then read off rows 0 and NN, the closed forms above. This is an identity, not an approximation: the Python audit proves it with sympy, and this page checks it row by row on the converged states, to within 10−1410^{-14}. The layer of the first-order discrete adjoint is therefore about (ν+h)/uin(\nu+h)/u_{\rm in} wide instead of ν/uin\nu/u_{\rm in}: 13.5 times wider at N=8N=8. On the cell-centred page the identity fails in the two end rows (boundary faces at distance h/2h/2); here there is no exception.

二阶格式在内部没有这一项。无限制器线性重构 σj=(lj+rj)/2\sigma_j=(l_j+r_j)/2 时,面 1≤f≤N−21\le f\le N-2 的迹之差是一个三阶差分,行 2≤j≤N−22\le j\le N-2 的耗散是一个四阶差分;两个边界面用单侧斜率,迹之差是二阶差分:

In the interior the second-order scheme has no such term. With unlimited linear reconstruction, σj=(lj+rj)/2\sigma_j=(l_j+r_j)/2, the jump of the traces of a face 1≤f≤N−21\le f\le N-2 is a third difference and the dissipation of a row 2≤j≤N−22\le j\le N-2 is a fourth difference; the two boundary faces use the one-sided slopes and their jump is a second difference:

qR−qL={−14(Uf+2−3Uf+1+3Uf−Uf−1)1≤f≤N−2,−14(U2−2U1+U0)f=0,+14(UN−2UN−1+UN−2)f=N−1,−(qR−qL)j+(qR−qL)j−1=14(Uj+2−4Uj+1+6Uj−4Uj−1+Uj−2)(2≤j≤N−2).q_R-q_L=\begin{cases}-\tfrac14\bigl(U_{f+2}-3U_{f+1}+3U_f-U_{f-1}\bigr)&1\le f\le N-2,\\[2pt] -\tfrac14\bigl(U_2-2U_1+U_0\bigr)&f=0,\\[2pt] +\tfrac14\bigl(U_N-2U_{N-1}+U_{N-2}\bigr)&f=N-1,\end{cases}\qquad -(q_R-q_L)_j+(q_R-q_L)_{j-1}=\tfrac14\bigl(U_{j+2}-4U_{j+1}+6U_j-4U_{j-1}+U_{j-2}\bigr)\quad(2\le j\le N-2).

这个四阶差分等于 h44uxxxx+O(h6)\tfrac{h^4}{4}u_{xxxx}+O(h^6):这是超黏性,单位长度上为 h34uxxxx\tfrac{h^3}{4}u_{xxxx},没有二阶导数型的人工黏性。第 1 行与第 N−1N-1 行的耗散是 14(U3−4U2+5U1−2U0)\tfrac14(U_3-4U_2+5U_1-2U_0) 与 14(UN−3−4UN−2+5UN−1−2UN)\tfrac14(U_{N-3}-4U_{N-2}+5U_{N-1}-2U_N)(sympy 证明;本页在随机状态上核对,差不超过 10−1410^{-14})。用精确节点值代入(N=4096N=4096),(qR−qL)/(h ux∗)(q_R-q_L)/(h\,u^*_x) 在面 0 上是 −0.00018,在面 1、2 上是 5.9×10−75.9\times10^{-7},在面 N−1N-1 上是 0.00018:和一阶格式的迹之差(比值 1)相比,两个边界面小一个 O(h)O(h) 的因子,内部面小一个 O(h2)O(h^2) 的因子,所以没有一个面带一阶格式那样大小为 hh 的额外黏性。第 3 节把两个边界面的二阶差分读成只作用在第 1 行与第 N−1N-1 行上、约为 h/4h/4 的额外黏性,其余各行只有四阶超黏性。格心页的两个端单元则带额外黏性 h/2h/2(比值 0.5001)。光滑限制器在 h∣ux∣≫ϵh|u_x|\gg\epsilon 时接近无限制器线性,h∣ux∣≪ϵh|u_x|\ll\epsilon 后内部面带 hh 而两个边界面(单侧斜率不受限制)带 h/2h/2:N=4096N=4096 时的比值在靠近两端的内部面上是 0.9985(全部内部面上介于 0.9981 与 1.0000 之间),在边界面上是 0.4992。所以,一阶格式里每一行都有的额外黏性 hh(它把伴随的层加宽到 (ν+h)/uin(\nu+h)/u_{\rm in})在二阶格式里不存在;第 1 行与第 N−1N-1 行上的 h/4h/4 在粗网格上对入口附近的伴随起什么作用,这里没有分离。

The fourth difference is h44uxxxx+O(h6)\tfrac{h^4}{4}u_{xxxx}+O(h^6): a hyperviscosity, h34uxxxx\tfrac{h^3}{4}u_{xxxx} per unit length, with no second-derivative artificial viscosity. Rows 1 and N−1N-1 are 14(U3−4U2+5U1−2U0)\tfrac14(U_3-4U_2+5U_1-2U_0) and 14(UN−3−4UN−2+5UN−1−2UN)\tfrac14(U_{N-3}-4U_{N-2}+5U_{N-1}-2U_N) (sympy proof; checked by this page on random states to within 10−1410^{-14}). With the exact nodal values (N=4096N=4096), (qR−qL)/(h ux∗)(q_R-q_L)/(h\,u^*_x) is −0.00018 on face 0, 5.9×10−75.9\times10^{-7} on faces 1 and 2 and 0.00018 on face N−1N-1: compared with the first-order jump (ratio 1) the jumps are smaller by a factor O(h)O(h) on the two boundary faces and O(h2)O(h^2) on the interior faces, so no face carries an added viscosity of the size hh of the first-order scheme. Section 3 reads the second difference of the two boundary faces as an added viscosity of about h/4h/4 acting on rows 1 and N−1N-1 only; every other row has only the fourth-order hyperviscosity. The two end cells of the cell-centred page carry h/2h/2 (ratio 0.5001). The smooth limiter is close to unlimited linear while h∣ux∣≫ϵh|u_x|\gg\epsilon; once h∣ux∣≪ϵh|u_x|\ll\epsilon the interior faces carry hh and the two boundary faces (one-sided slope, not limited) h/2h/2: the ratios at N=4096N=4096 are 0.9985 (interior faces next to the ends; between 0.9981 and 1.0000 over all interior faces) and 0.4992 (boundary faces). So the added viscosity hh of every row, which widens the layer of the first-order adjoint to (ν+h)/uin(\nu+h)/u_{\rm in}, is absent at second order; what the h/4h/4 of rows 1 and N−1N-1 does to the adjoint next to the inlet on coarse meshes is not isolated here.

图 94 · 一阶离散伴随(点,内部节点)、黏性 ν 的连续伴随 λ_ν(实线)与黏性 ν+h 的连续伴随 λ_(ν+h)(虚线),只画 x ≤ 0.3。离散伴随的层远比 ν/u_in 宽,点更贴近虚线。在层内(x ≤ 5(ν+h)/u_in),N=4096 时到 λ_(ν+h) 的最大偏差是到 λ_ν 的 1/26。λ(黏性 ν)黏性 ν + h 的连续伴随一阶离散伴随 ψj​−1.6−1.4−1.2−1−0.8−0.6−0.4−0.2000.10.20.3x伴随N = 8,ν + h = 0.135−1.6−1.4−1.2−1−0.8−0.6−0.4−0.2000.10.20.3xN = 32,ν + h = 0.0413−1.6−1.4−1.2−1−0.8−0.6−0.4−0.2000.10.20.3xN = 128,ν + h = 0.0178
图 94 · 一阶离散伴随(点,内部节点)、黏性 ν\nu 的连续伴随 λν\lambda_\nu(实线)与黏性 ν+h\nu+h 的连续伴随 λν+h\lambda_{\nu+h}(虚线),只画 x≤0.3x\le0.3。离散伴随的层远比 ν/uin\nu/u_{\rm in} 宽,点更贴近虚线。在层内(x≤5(ν+h)/uinx\le5(\nu+h)/u_{\rm in}),N=4096N=4096 时到 λν+h\lambda_{\nu+h} 的最大偏差是到 λν\lambda_\nu 的 1/26。
Figure 94 · The first-order discrete adjoint (dots, interior nodes), the continuous adjoint λ_ν of viscosity ν (solid) and λ_(ν+h) of viscosity ν+h (dashed), for x ≤ 0.3. The layer of the discrete adjoint is far wider than ν/u_in; the dots are closer to the dashed curve. Inside the layer (x ≤ 5(ν+h)/u_in) the largest deviation from λ_(ν+h) at N=4096 is 1/26 of that from λ_ν.λ (viscosity ν)continuous adjoint with viscosity ν + hfirst-order discrete adjoint ψj​−1.6−1.4−1.2−1−0.8−0.6−0.4−0.2000.10.20.3xadjointN = 8, ν + h = 0.135−1.6−1.4−1.2−1−0.8−0.6−0.4−0.2000.10.20.3xN = 32, ν + h = 0.0413−1.6−1.4−1.2−1−0.8−0.6−0.4−0.2000.10.20.3xN = 128, ν + h = 0.0178
Figure 94 · The first-order discrete adjoint (dots, interior nodes), the continuous adjoint λν\lambda_\nu of viscosity ν\nu (solid) and λν+h\lambda_{\nu+h} of viscosity ν+h\nu+h (dashed), for x≤0.3x\le0.3. The layer of the discrete adjoint is far wider than ν/uin\nu/u_{\rm in}; the dots are closer to the dashed curve. Inside the layer (x≤5(ν+h)/uinx\le5(\nu+h)/u_{\rm in}) the largest deviation from λν+h\lambda_{\nu+h} at N=4096N=4096 is 1/26 of that from λν\lambda_\nu.

测量结果:到 N=2048N=2048 为止两个最大偏差都在伴随的层里;到 λν+h\lambda_{\nu+h} 的最大偏差在每个网格上都比到 λν\lambda_\nu 的小(N=8N=8 时是后者的 1/3.8,N=4096N=4096 时是 1/26.2),但两者最后都按一阶下降(N=2048N=2048 到 4096 的观测阶 1.00 与 0.98);N=4096N=4096 时到 λν+h\lambda_{\nu+h} 的最大偏差已离开层(在 x=0.129x=0.129)。等效黏性解释了层里的偏差,不是全部误差:在 L1 范数下两个距离之比只有 1.52(N=1024N=1024:2.03e−3 与 1.33e−3,最大偏差之比为 24.6):到 λν+h\lambda_{\nu+h} 的 L1 距离有 92% 在层外,到 λν\lambda_\nu 的有 73% 在层内(层取 x≤5(ν+h)/uinx\le5(\nu+h)/u_{\rm in})。层外 O(h)O(h) 的那部分误差的来源这里没有分离。

Measured: up to N=2048N=2048 both largest deviations sit in the adjoint's layer; the largest deviation from λν+h\lambda_{\nu+h} is smaller than that from λν\lambda_\nu on every mesh (3.8 times at N=8N=8, 26.2 times at N=4096N=4096), but both finally fall at first order (observed orders 1.00 and 0.98 from N=2048N=2048 to 4096), and at N=4096N=4096 the largest deviation from λν+h\lambda_{\nu+h} has left the layer (it is at x=0.129x=0.129). The effective viscosity explains the deviation inside the layer, not the whole error: in the L1 norm the two distances differ by a factor of only 1.52 (N=1024N=1024: 2.03e−3 and 1.33e−3, against 24.6 for the largest deviations): 92% of the L1 distance to λν+h\lambda_{\nu+h} lies outside the layer, while 73% of that to λν\lambda_\nu lies inside it (the layer taken as x≤5(ν+h)/uinx\le5(\nu+h)/u_{\rm in}). The source of the O(h)O(h) error outside the layer is not isolated here.

边界层、渐近行为与黏性 ν 的作用

The inlet layer, its asymptotics and the effect of ν

连续梯度的边界项含 νλx(0) ∂Dkuin\nu\lambda_x(0)\,\partial_{D_k}u_{\rm in},而 ν\nu 越小,∣λx(0)∣|\lambda_x(0)| 越大。先看 λ\lambda 的边界层结构(连续伴随问题的形式渐近分析,不是证明)。层外黏性项可以略去,−uλx≈−(1+x)-u\lambda_x\approx-(1+x),且 λ(1)=0\lambda(1)=0(伴随从 x=1x=1 向上游传):

The boundary term of the continuous gradient contains νλx(0) ∂Dkuin\nu\lambda_x(0)\,\partial_{D_k}u_{\rm in}, while ∣λx(0)∣|\lambda_x(0)| grows as ν\nu decreases. First the structure of the layer of λ\lambda (a formal asymptotic analysis of the continuous adjoint problem, not a proof). Outside the layer the viscous term can be dropped, −uλx≈−(1+x)-u\lambda_x\approx-(1+x), with λ(1)=0\lambda(1)=0 (the adjoint travels upstream from x=1x=1):

λout(x)=−∫x11+tu∗(t) dt,λout(0)=−∫011+tu∗(t) dt=−1.561867.\lambda_{\rm out}(x)=-\int_x^1\frac{1+t}{u^*(t)}\,\mathrm dt,\qquad \lambda_{\rm out}(0)=-\int_0^1\frac{1+t}{u^*(t)}\,\mathrm dt=−1.561867.

λout(0)≠0\lambda_{\rm out}(0)\ne0,而边界条件要求 λ(0)=0\lambda(0)=0,所以 x=0x=0 处必须有层。层内令 ξ=uinx/ν\xi=u_{\rm in}x/\nu,主导项满足 λξξ+λξ=0\lambda_{\xi\xi}+\lambda_\xi=0,解为 C1+C2e−ξC_1+C_2e^{-\xi};由 λ(0)=0\lambda(0)=0 及与 λout\lambda_{\rm out} 的匹配得到

λout(0)≠0\lambda_{\rm out}(0)\ne0 while the boundary condition asks for λ(0)=0\lambda(0)=0, so there must be a layer at x=0x=0. Inside it, with ξ=uinx/ν\xi=u_{\rm in}x/\nu, the leading terms satisfy λξξ+λξ=0\lambda_{\xi\xi}+\lambda_\xi=0, with the solutions C1+C2e−ξC_1+C_2e^{-\xi}; λ(0)=0\lambda(0)=0 and matching with λout\lambda_{\rm out} give

λ(x)≈λout(x)−λout(0) e−ξ,λx(0)≈uin λout(0)ν,ν λx(0)≈uin λout(0)=−1.42887.\lambda(x)\approx\lambda_{\rm out}(x)-\lambda_{\rm out}(0)\,e^{-\xi},\qquad \lambda_x(0)\approx\frac{u_{\rm in}\,\lambda_{\rm out}(0)}{\nu},\qquad \nu\,\lambda_x(0)\approx u_{\rm in}\,\lambda_{\rm out}(0)=−1.42887.

斜率按 1/ν1/\nu 增长,而 νλx(0)\nu\lambda_x(0) 却在 ν→0\nu\to0 时保持 O(1)O(1):它等于层两侧的跳跃 λout(0)−0\lambda_{\rm out}(0)-0 乘以 uinu_{\rm in},与黏性无关——这个量 μ0=νλx(0)\mu_0=\nu\lambda_x(0) 正是本节的乘子 ψ0\psi_0 要逼近的。数值验证:ν=0.01\nu=0.01 时 Chebyshev 解给出 νλx(0)=−1.42657\nu\lambda_x(0)=−1.42657,渐近值为 −1.42887;ν\nu 较小时差别约与 ν\nu 成正比(下表)。

The slope grows like 1/ν1/\nu, but νλx(0)\nu\lambda_x(0) stays O(1)O(1) as ν→0\nu\to0: it equals the jump λout(0)−0\lambda_{\rm out}(0)-0 across the layer times uinu_{\rm in}, independent of the viscosity. This is the quantity μ0=νλx(0)\mu_0=\nu\lambda_x(0) that the multiplier ψ0\psi_0 of this section has to approach. Numerically, at ν=0.01\nu=0.01 the Chebyshev solution gives νλx(0)=−1.42657\nu\lambda_x(0)=−1.42657 against the asymptotic −1.42887; for small ν\nu the difference is roughly proportional to ν\nu (the table below).

把 ν\nu 从 0.1 减到 0.001(aa、φ\varphi 不变),连续伴随的层越来越薄,∣λx(0)∣|\lambda_x(0)| 按 1/ν1/\nu 增长,νλx(0)\nu\lambda_x(0) 则趋于渐近值 uinλout(0)u_{\rm in}\lambda_{\rm out}(0)。差值除以 ν\nu(表中“差 /ν/\nu”一列)从 ν=0.1\nu=0.1 时的 0.758 变到 ν=0.001\nu=0.001 时的 0.188。源项积分和边界项各自随 ν\nu 变化,它们的和——精确梯度——不变。最后一列是固定网格 N=64N=64(无限制器线性)上的乘子 ψ0\psi_0:ν\nu 从 0.1 减到 0.001,hh 从伴随层宽的 0.14 倍增大到 14.3 倍,ψ0÷νλx(0)\psi_0\div\nu\lambda_x(0) 却始终在 0.9941 到 0.9991 之间,而斜率比从 0.95 降到 0.089。下表用 Chebyshev 解(201 个点;Python 审计比对 241 与 321 个点,差都小于 10−1210^{-12}),分量 aa:

Decrease ν\nu from 0.1 to 0.001 (aa, φ\varphi fixed): the layer of the continuous adjoint gets thinner, ∣λx(0)∣|\lambda_x(0)| grows like 1/ν1/\nu, and νλx(0)\nu\lambda_x(0) tends to the asymptotic value uinλout(0)u_{\rm in}\lambda_{\rm out}(0). The difference divided by ν\nu (the column “gap/ν/\nu”) goes from 0.758 at ν=0.1\nu=0.1 to 0.188 at ν=0.001\nu=0.001. The source integral and the boundary term each change with ν\nu; their sum, the exact gradient, does not. The last column is the multiplier ψ0\psi_0 on the fixed mesh N=64N=64 (unlimited linear): as ν\nu falls from 0.1 to 0.001, hh grows from 0.14 to 14.3 times the width of the adjoint's layer, yet ψ0÷νλx(0)\psi_0\div\nu\lambda_x(0) stays between 0.9941 and 0.9991, while the slope ratio falls from 0.95 to 0.089. The table uses the Chebyshev solutions (201 points; the Python audit compares 241 with 321 points and finds differences below 10−1210^{-12}), component aa:

ν\nuλx(0)\lambda_x(0)νλx(0)\nu\lambda_x(0)uinλout(0)u_{\rm in}\lambda_{\rm out}(0)差 /ν/\nugap/ν/\nu源项积分source integral边界项boundary term和 =dJ/da=\mathrm dJ/\mathrm dasum =dJ/da=\mathrm dJ/\mathrm daψ0\psi_0(N=64N=64)ψ0\psi_0 (N=64N=64)
0.1−13.530−1.35304−1.428870.7580.5257−0.6697−0.144008−1.3518
0.05−28.095−1.40474−1.428870.4820.5018−0.6458−0.144008−1.4027
0.02−71.155−1.42310−1.428870.2880.4808−0.6248−0.144008−1.4193
0.01−142.657−1.42657−1.428870.2300.4728−0.6168−0.144008−1.4212
0.005−285.568−1.42784−1.428870.2050.4686−0.6126−0.144008−1.4211
0.002−714.240−1.42848−1.428870.1920.4661−0.6101−0.144008−1.4206
0.001−1428.677−1.42868−1.428870.1880.4652−0.6092−0.144008−1.4203
图 95 · 黏性对连续伴随的作用(a=0.2,φ=0.07)。(a) λ(x):粗线是 ν=0.01;(b) 用层变量 ξ=u_inx/ν 画 (λ-λ_out)/(-λ_out(0)):ν 越小越贴近 e^(-ξ)(点线),即上面的两项近似;(c) ν 减小时,νλ_x(0) 趋于 u_inλ_out(0)=−1.4289;ν → 0 时边界项并不消失;橙黄圈是固定网格 N=64 上的乘子 ψ_0,它几乎落在曲线上。−1.6−1.4−1.2−1−0.8−0.6−0.4−0.2000.20.40.60.81xλ(x)(a) λ(x),ν 从 0.1 到 0.00100.20.40.60.81012345678ξ = uin​ x/ν(b) (λ − λout​)/(−λout​(0)) 与 e−ξ​(点线)ν = 0.1ν = 0.05ν = 0.02ν = 0.01ν = 0.005ν = 0.002ν = 0.001ν λx​(0)(Chebyshev)渐近值 uin​ λout​(0)ψ0​(N = 64,无限制器)−1.44−1.42−1.4−1.38−1.36−1.340.0010.010.1νν λx​(0)
图 95 · 黏性对连续伴随的作用(a=0.2a=0.2,φ=0.07\varphi=0.07)。(a) λ(x)\lambda(x):粗线是 ν=0.01\nu=0.01;(b) 用层变量 ξ=uinx/ν\xi=u_{\rm in}x/\nu 画 (λ−λout)/(−λout(0))(\lambda-\lambda_{\rm out})/(-\lambda_{\rm out}(0)):ν\nu 越小越贴近 e−ξe^{-\xi}(点线),即上面的两项近似;(c) ν\nu 减小时,νλx(0)\nu\lambda_x(0) 趋于 uinλout(0)=−1.4289u_{\rm in}\lambda_{\rm out}(0)=−1.4289;ν→0\nu\to0 时边界项并不消失;橙黄圈是固定网格 N=64N=64 上的乘子 ψ0\psi_0,它几乎落在曲线上。
Figure 95 · The effect of the viscosity on the continuous adjoint (a=0.2, φ=0.07). (a) λ(x), the thick line is ν=0.01; (b) (λ-λ_out)/(-λ_out(0)) against the layer variable ξ=u_inx/ν: the smaller ν, the closer to e^(-ξ) (dotted), the two-term approximation above; (c) as ν decreases, νλ_x(0) tends to u_inλ_out(0)=−1.4289: the boundary term does not vanish as ν → 0; the amber rings are the multiplier ψ_0 on the fixed mesh N=64, almost on the curve.−1.6−1.4−1.2−1−0.8−0.6−0.4−0.2000.20.40.60.81xλ(x)(a) λ(x) for ν from 0.1 to 0.00100.20.40.60.81012345678ξ = uin​ x/ν(b) (λ − λout​)/(−λout​(0)) and e−ξ​ (dotted)ν = 0.1ν = 0.05ν = 0.02ν = 0.01ν = 0.005ν = 0.002ν = 0.001ν λx​(0) (Chebyshev)asymptote uin​ λout​(0)ψ0​ (N = 64, none)−1.44−1.42−1.4−1.38−1.36−1.340.0010.010.1νν λx​(0)
Figure 95 · The effect of the viscosity on the continuous adjoint (a=0.2a=0.2, φ=0.07\varphi=0.07). (a) λ(x)\lambda(x), the thick line is ν=0.01\nu=0.01; (b) (λ−λout)/(−λout(0))(\lambda-\lambda_{\rm out})/(-\lambda_{\rm out}(0)) against the layer variable ξ=uinx/ν\xi=u_{\rm in}x/\nu: the smaller ν\nu, the closer to e−ξe^{-\xi} (dotted), the two-term approximation above; (c) as ν\nu decreases, νλx(0)\nu\lambda_x(0) tends to uinλout(0)=−1.4289u_{\rm in}\lambda_{\rm out}(0)=−1.4289: the boundary term does not vanish as ν→0\nu\to0; the amber rings are the multiplier ψ0\psi_0 on the fixed mesh N=64N=64, almost on the curve.

在面板里拖动 ν\nu,同时看固定网格上的离散伴随:ν\nu 越小层越难分辨,斜率 ψ1/h\psi_1/h 离 λx(0)\lambda_x(0) 越远,而乘子 ψ0\psi_0 与 νλx(0)\nu\lambda_x(0) 的比值几乎不动。

Drag ν\nu in the panel and watch the discrete adjoint on a fixed mesh: the smaller ν\nu, the harder the layer is to resolve and the further the slope ψ1/h\psi_1/h is from λx(0)\lambda_x(0), while the ratio of the multiplier ψ0\psi_0 to νλx(0)\nu\lambda_x(0) hardly moves.

梯度误差的逐项分解

The gradient error, part by part

第 12 节在固定网格上分清了设计进入残差的路径。对 aa 与 φ\varphi(k=0,1k=0,1)只有两条:每个内部行的积分源项,以及两个约束行里的边界值。所以离散梯度与连续梯度可以逐项对齐(上面已写出)。对 k=2k=2 还有面通量里显含的 ν\nu 一项:离散的是 ∑fH˙f Ψf\sum_f\dot H_f\,\Psi_f,连续的是 −∫01λ uxx∗ dx-\int_0^1\lambda\,u^*_{xx}\,\mathrm dx(它与源项部分的 ν\nu 导数相消)。三部分之和与 RDTψR_D^T\psi 相差不到 10−1410^{-14}(本页和审计都核对过);把梯度精确地分成内部行与两个约束行两部分,写在附录 A 的 A.7 里。下表是分量 aa(无限制器线性);连续值为:源项积分 0.4728,入口项 −0.6074,出口项 −0.0094,梯度 −0.1440:

Section 12 separated the paths by which the design enters the residual, on a fixed mesh. For aa and φ\varphi (k=0,1k=0,1) there are only two: the integrated source of every interior row, and the boundary values in the two constraint rows. So the discrete and the continuous gradient can be lined up term by term (written out above). For k=2k=2 there is also the explicit ν\nu of the face flux: ∑fH˙f Ψf\sum_f\dot H_f\,\Psi_f in the discrete gradient, −∫01λ uxx∗ dx-\int_0^1\lambda\,u^*_{xx}\,\mathrm dx in the continuous one (it cancels the ν\nu-derivative of the source part). The three parts add up to RDTψR_D^T\psi to within 10−1410^{-14} (checked by this page and by the audit); the exact split of the gradient into the interior rows and the two constraint rows is written out in Appendix A (A.7). The table is for component aa (unlimited linear); the continuous values are: source integral 0.4728, inlet term −0.6074, outlet term −0.0094, gradient −0.1440:

N源项行source rows入口项 −ψ0 ∂uin-\psi_0\,\partial u_{\rm in}inlet −ψ0 ∂uin-\psi_0\,\partial u_{\rm in}出口项 −ψN ∂uout-\psi_N\,\partial u_{\rm out}outlet −ψN ∂uout-\psi_N\,\partial u_{\rm out}Dˉk=dJh/dDk\bar D_k=\mathrm dJ_h/\mathrm dD_kDˉk=dJh/dDk\bar D_k=\mathrm dJ_h/\mathrm dD_k与精确值之差minus exact
80.4577−0.5987−0.0370−0.1781−3.4e−2
160.4884−0.5966−0.0220−0.13011.4e−2
320.4782−0.6019−0.0150−0.13875.3e−3
640.4740−0.6051−0.0116−0.14281.2e−3
1280.4730−0.6066−0.0102−0.14381.9e−4
2560.4728−0.6072−0.0096−0.14402.1e−5
5120.4728−0.6073−0.0094−0.14407.7e−7
10240.4728−0.6074−0.0094−0.1440−4.4e−7

分量 φ\varphi 的连续值:源项积分 1.7323,入口项 −1.6221,出口项 −0.0251,梯度 0.0852:

The continuous values of component φ\varphi: source integral 1.7323, inlet term −1.6221, outlet term −0.0251, gradient 0.0852:

N源项行source rows入口项 −ψ0 ∂uin-\psi_0\,\partial u_{\rm in}inlet −ψ0 ∂uin-\psi_0\,\partial u_{\rm in}出口项 −ψN ∂uout-\psi_N\,\partial u_{\rm out}outlet −ψN ∂uout-\psi_N\,\partial u_{\rm out}Dˉk=dJh/dDk\bar D_k=\mathrm dJ_h/\mathrm dD_kDˉk=dJh/dDk\bar D_k=\mathrm dJ_h/\mathrm dD_k与精确值之差minus exact
82.1176−1.5988−0.09890.41993.3e−1
161.8164−1.5932−0.05870.16467.9e−2
321.7486−1.6073−0.04000.10131.6e−2
641.7349−1.6160−0.03110.08782.6e−3
1281.7325−1.6199−0.02720.08542.6e−4
2561.7323−1.6214−0.02570.0851−1.5e−5
5121.7323−1.6219−0.02520.0851−1.7e−5
10241.7323−1.6220−0.02510.0851−6.0e−6

四点观察。(1) N=8N=8 时分量 aa 的各部分误差是:源项行 −0.0151,入口项 0.0087,出口项 −0.0277:最大的是出口项,因为 ψN\psi_N 是连续值的 3.95 倍(见“核心结果”一节);入口项相对最准,对应乘子 ψ0\psi_0 只差 1.4%。(2) 分量 φ\varphi 在 N=8N=8 时误差在源项行(0.385,入口项 0.023,出口项 −0.074)。(3) 源项行与连续的源项积分并不是逐个控制体对应的:连续的源项积分里,第一个半控制体 V0=[0,h/2]V_0=[0,h/2] 一项(−∫V0λ ∂as dx-\int_{V_0}\lambda\,\partial_as\,\mathrm dx)在 N=8N=8 时是 0.4306,占 91%,而离散格式没有第 0 个源项行(约束行不带源项)。把离散源项和里的 ψj\psi_j 换成采样的 λ(xj)\lambda(x_j),这个和从 0.4577 降到 0.0306,差 0.4271,是 V0V_0 一项的 99%:入口附近的内部节点(ψ1\psi_1 偏离 λ(x1)\lambda(x_1) 达 21%)把这块缺失的源项补了回来。逐节点看,∫Vj(λ−ψj) ∂as dx\int_{V_j}(\lambda-\psi_j)\,\partial_as\,\mathrm dx 在第 1 个节点上是 0.243,其余节点上最大 0.063。(4) 各部分都是 O(1)O(1),梯度却只有 −0.144:N=8N=8 时 Dˉ0=−0.1781\bar D_0=−0.1781,是精确值的 1.24 倍;Dˉ1=0.4199\bar D_1=0.4199 是精确值的 4.9 倍。渐近地,入口项和出口项的误差二阶收敛(N=2048N=2048 到 4096 的阶:入口 1.98,出口 1.98),并且几乎大小相等、符号相反(见“核心结果”一节),所以梯度误差是源项行的误差加上两个边界项剩下的一小部分:N=4096N=4096 时源项行为 −7.1e−8,边界项合计 1.3e−8(梯度误差 −5.9e−8),而 N=512N=512 时边界项的剩余 5.8e−7 反而大于源项行的误差 1.9e−7。源项行的误差在 N=8N=8 与 16 之间变号,又在 N=512N=512 与 1024 之间变号,它的观测阶(1.75)只有参考意义。

Four observations. (1) At N=8N=8 the errors of the parts of component aa are: source rows −0.0151, inlet term 0.0087, outlet term −0.0277: the largest is the outlet term, because ψN\psi_N is 3.95 times its continuous value (see the subsection “The central result”); the inlet term is relatively the most accurate, matching the multiplier ψ0\psi_0 that is off by only 1.4%. (2) For component φ\varphi at N=8N=8 the error is in the source rows (0.385, against 0.023 for the inlet term and −0.074 for the outlet term). (3) The source rows do not correspond to the continuous source integral volume by volume: in the continuous integral the first half volume V0=[0,h/2]V_0=[0,h/2] contributes −∫V0λ ∂as dx=0.4306-\int_{V_0}\lambda\,\partial_as\,\mathrm dx=0.4306 at N=8N=8, 91% of it, and the discrete scheme has no source row 0 (a constraint row carries no source). With the sampled λ(xj)\lambda(x_j) in place of ψj\psi_j the discrete source sum falls from 0.4577 to 0.0306; the difference, 0.4271, is 99% of the V0V_0 term: the interior nodes next to the inlet (ψ1\psi_1 is off from λ(x1)\lambda(x_1) by 21%) make up for the missing source. Node by node, ∫Vj(λ−ψj) ∂as dx\int_{V_j}(\lambda-\psi_j)\,\partial_as\,\mathrm dx is 0.243 at node 1 and at most 0.063 at the others. (4) The parts are O(1)O(1) while the gradient is only −0.144: at N=8N=8, Dˉ0=−0.1781\bar D_0=−0.1781 is 1.24 times the exact value and Dˉ1=0.4199\bar D_1=0.4199 is 4.9 times. Asymptotically the errors of the inlet and outlet terms converge at second order (orders between N=2048N=2048 and N=4096N=4096: inlet 1.98, outlet 1.98) and are nearly equal and opposite (see the subsection “The central result”), so the gradient error is the error of the source rows plus the small remainder of the two boundary terms: at N=4096N=4096 the source rows give −7.1e−8 and the boundary terms together 1.3e−8 (gradient error −5.9e−8), but at N=512N=512 the boundary remainder, 5.8e−7, is larger than the error of the source rows, 1.9e−7. The error of the source rows changes sign between N=8N=8 and 16 and again between N=512N=512 and 1024, so its observed order (1.75) is only indicative.

图 96 · 梯度误差随 N 的逐项分解(无限制器线性,默认设计):每一部分离散值与连续值之差,以及梯度误差(粗线)。粗网格上,分量 a 的误差主要在出口项和源项行,分量 φ 的误差主要在源项行;各部分渐近地约二阶收敛。源项行 1…N−1入口乘子项 −ψ0​ uin​′出口乘子项 −ψN​ uout​′梯度误差(总和)10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​1101001000N|离散部分 − 连续部分|(a) 分量 a10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​1101001000N(b) 分量 φ
图 96 · 梯度误差随 NN 的逐项分解(无限制器线性,默认设计):每一部分离散值与连续值之差,以及梯度误差(粗线)。粗网格上,分量 aa 的误差主要在出口项和源项行,分量 φ\varphi 的误差主要在源项行;各部分渐近地约二阶收敛。
Figure 96 · The gradient error part by part against N (unlimited linear, default design): the difference between the discrete and the continuous value of each part, and the gradient error (thick). On coarse meshes the error of component a sits in the outlet term and the source rows, that of φ in the source rows; asymptotically every part converges at about second order.source rows 1…N−1inlet term −ψ0​ uin​′outlet term −ψN​ uout​′gradient error (sum)10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​1101001000N|discrete part − continuous part|(a) component a10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​1101001000N(b) component φ
Figure 96 · The gradient error part by part against NN (unlimited linear, default design): the difference between the discrete and the continuous value of each part, and the gradient error (thick). On coarse meshes the error of component aa sits in the outlet term and the source rows, that of φ\varphi in the source rows; asymptotically every part converges at about second order.

离散梯度趋于什么,又不是什么

What the discrete gradient converges to, and what it is not

RDTψR_D^T\psi 是离散目标 Jh(D)=wT𝐔(D)J_h(D)=w^T\mathbf U(D) 的梯度,精确到舍入误差。离散目标本身就带着梯形公式的误差:对精确节点值,Jh(u∗)−J∗=h212ux∗(0)+O(h4)J_h(u^*)-J^*=\tfrac{h^2}{12}u^*_x(0)+O(h^4)(Euler–Maclaurin:u∗u^* 是周期的,所以 ((1+x)u∗)′((1+x)u^*)' 在两端相差 ux∗(0)u^*_x(0));N=8N=8 时左边是 1.50e−3,右边第一项是 1.48e−3。把这个目标对设计求导,即使状态是精确的,梯度也已带有 h212∂Dkux∗(0)\tfrac{h^2}{12}\partial_{D_k}u^*_x(0) 这一项。于是 aa 分量的梯度误差分成两部分:梯形公式作用在精确节点灵敏度上的部分,加上切线解 vv 的离散误差经 ww 加权的余项:

RDTψR_D^T\psi is the gradient of the discrete objective Jh(D)=wT𝐔(D)J_h(D)=w^T\mathbf U(D), exact up to rounding. The discrete objective carries the error of the trapezoid rule itself: for the exact nodal values Jh(u∗)−J∗=h212ux∗(0)+O(h4)J_h(u^*)-J^*=\tfrac{h^2}{12}u^*_x(0)+O(h^4) (Euler–Maclaurin: u∗u^* is periodic, so ((1+x)u∗)′((1+x)u^*)' jumps by ux∗(0)u^*_x(0) between the ends); at N=8N=8 the left side is 1.50e−3 and the first term on the right 1.48e−3. Differentiated with respect to the design, this objective gives a gradient with the term h212∂Dkux∗(0)\tfrac{h^2}{12}\partial_{D_k}u^*_x(0) even if the state were exact. The error of the aa component therefore splits into the part of the trapezoid rule applied to the exact nodal sensitivities, plus a remainder, the discretisation error of the tangent solution vv weighted with ww:

Naa 梯度误差aa-gradient error梯形公式的部分(精确节点灵敏度)trapezoid part (exact nodal sensitivities)h212∂aux∗(0)\tfrac{h^2}{12}\partial_au^*_x(0)h212∂aux∗(0)\tfrac{h^2}{12}\partial_au^*_x(0)余项(状态的离散误差)remainder (discretisation error of the state)
8−3.41e−27.48e−37.40e−3−4.15e−2
325.33e−34.63e−44.63e−44.86e−3
1281.89e−42.89e−52.89e−51.60e−4
5127.71e−71.81e−61.81e−6−1.04e−6
1024−4.38e−74.52e−74.52e−7−8.90e−7
2048−1.93e−71.13e−71.13e−7−3.05e−7
4096−5.87e−82.82e−82.82e−8−8.70e−8

梯形部分单调地按二阶下降,并且符号固定;余项的符号在 N=8N=8 和 N≥512N\ge512 时与它相反(在 N=16N=16 到 256 之间相同),所以 NN 大到一定程度后两者部分相消:aa 分量的总误差在 N=8N=8 与 16 之间变号(−3.4e−2 与 1.4e−2),又在 N=512N=512 与 1024 之间变号(7.7e−7 与 −4.4e−7),φ\varphi 分量在 N=128N=128 与 256 之间变号,ν\nu 分量在 N=8N=8 与 16 之间变号,又在 N=1024N=1024 与 2048 之间变号;所以无限制器线性的梯度误差的观测阶在这些点附近是不规则的,没有意义。Python 数据最细两层(N=8192N=8192 到 16384)上三个分量的观测阶:无限制器线性 1.94、1.98、1.85,一阶 1.00、1.00、0.99,光滑限制器 0.99、0.98、1.43。N=8N=8 时梯形部分是总误差的 −22%,N=4096N=4096 时是 −48%。所以:离散梯度是这个网格上 JhJ_h 的梯度;它趋于连续目标 JJ 的梯度,但在粗网格上与它相差很大(N=16N=16 时 aa、φ\varphi 分量分别差 10% 与 93%,N=64N=64 时差 0.8% 与 3.1%;N<91N<91 时层没被分辨):N=8N=8 时 (−0.1781, 0.4199, 0.0039)(−0.1781,\ 0.4199,\ 0.0039),连续值是 (−0.1440, 0.0852, 0)(−0.1440,\ 0.0852,\ 0);φ\varphi 分量差 0.335,是连续值的 3.9 倍(离散值是连续值的 4.9 倍)。和格心页比较,格点格式并不处处更好。无限制器线性、N=8N=8 时(格心页的梯度是 (−0.4866, −0.0610, −0.3099)(−0.4866,\ −0.0610,\ −0.3099)):aa 分量的误差是格心页的 1/10.1,ν\nu 分量是 1/79,φ\varphi 分量却更大(0.335,格心页 0.146)。在 Python 数据的各个网格上(N=32N=32 到 16384):无限制器线性在三个分量上的误差都比格心页小(节点与格心的误差之比:aa 从 3.7e−4 到 5.0e−2,φ\varphi 从 2.9e−3 到 3.7e−1,ν\nu 从 2.6e−4 到 4.1e−1);一阶格式的 aa、φ\varphi 分量并不更好(之比 1.01 到 1.42 与 1.02 到 5.13),只有 ν\nu 分量更好。

The trapezoid part falls monotonically at second order and keeps its sign; the remainder has the opposite sign at N=8N=8 and from N=512N=512 on (the same sign from N=16N=16 to 256), so for large NN the two partly cancel: the total error of the aa component changes sign between N=8N=8 and 16 (−3.4e−2 and 1.4e−2) and again between N=512N=512 and 1024 (7.7e−7 and −4.4e−7), that of φ\varphi between N=128N=128 and 256, that of ν\nu between N=8N=8 and 16 and again between N=1024N=1024 and 2048; so the observed orders of the gradient errors of unlimited linear reconstruction are erratic near these points and mean nothing there. Between the two finest levels of the Python data (N=8192N=8192 to 16384) the observed orders of the three components are 1.94, 1.98 and 1.85 for unlimited linear, 1.00, 1.00 and 0.99 for the first-order scheme, 0.99, 0.98 and 1.43 for the smooth limiter. At N=8N=8 the trapezoid part is −22% of the total error, at N=4096N=4096 it is −48%. So: the discrete gradient is the gradient of JhJ_h on this mesh; it approaches the gradient of the continuous objective JJ, but on coarse meshes it is far from it (at N=16N=16 the aa and φ\varphi components are off by 10% and 93%, at N=64N=64 by 0.8% and 3.1%; the layer is unresolved for N<91N<91): at N=8N=8 it is (−0.1781, 0.4199, 0.0039)(−0.1781,\ 0.4199,\ 0.0039) against the continuous (−0.1440, 0.0852, 0)(−0.1440,\ 0.0852,\ 0); the φ\varphi component is off by 0.335, 3.9 times the continuous value (the discrete value is 4.9 times it). Compared with the cell-centred page the node scheme is not better everywhere. Unlimited linear at N=8N=8 (the cell page's gradient is (−0.4866, −0.0610, −0.3099)(−0.4866,\ −0.0610,\ −0.3099)): the aa component is 10.1 times more accurate and the ν\nu component 79 times, but the φ\varphi component is worse (0.335 against 0.146). On every mesh of the Python data (N=32N=32 to 16384) the error of unlimited linear is smaller than the cell page's in all three components (ratios node/cell: aa from 3.7e−4 to 5.0e−2, φ\varphi from 2.9e−3 to 3.7e−1, ν\nu from 2.6e−4 to 4.1e−1); for the first-order scheme the aa and φ\varphi components are not better (ratios 1.01 to 1.42 and 1.02 to 5.13), only the ν\nu component is.

反面例子:边界面的距离取成 h/2

A counterexample: the boundary-face distance taken as h/2

一个看似无害的错误:把格心页的做法带过来,把两个边界面的黏性距离取成 d0=dN−1=h/2d_0=d_{N-1}=h/2(格心页的边界面离未知量只有半个单元),而格点格式里每个面两侧都是节点,距离处处是 hh(第 3 节)。错误版本的残差 R~\tilde R 只在两行不同:

A harmless-looking slip: carry over the practice of the cell-centred page and take the viscous distance of the two boundary faces as d0=dN−1=h/2d_0=d_{N-1}=h/2 (on the cell-centred page the boundary face is half a cell from its unknown), while on the node mesh every face has a node on each side and the distance is hh everywhere (Section 3). The residual of the slip, R~\tilde R, differs from the page's in two rows only:

R~1=R1+νh (U1−U0),R~N−1=RN−1−νh (UN−UN−1),R~j=Rj(j≠1,N−1).\tilde R_1=R_1+\frac{\nu}{h}\,(U_1-U_0),\qquad \tilde R_{N-1}=R_{N-1}-\frac{\nu}{h}\,(U_N-U_{N-1}),\qquad \tilde R_j=R_j\quad(j\ne1,N-1).

它的切线、反向和复数语句写在本节的模块里,用点积检验和复数步长核对,二者都在舍入误差内一致(点积检验按 10−1410^{-14} 的标准,与模型同样的检查);Python 审计只改自己的距离数组,独立地复现了下面的每个数。

Its tangent, reverse and complex statements are written in this section's module and checked like the model's, by the dot test and complex step, both agreeing to rounding (the dot test is held to 10−1410^{-14}, as for the model); the Python audit reproduces every number below independently, changing only its distance array.

R~1\tilde R_1 不相容:代入精确节点值,本页的 R1R_1 是 O(h2)O(h^2)(N=4096N=4096 时 R1/h2=−1.224R_1/h^2=−1.224;内部各行是 O(h3)O(h^3)),错误版本的 R~1\tilde R_1 却趋于常数 νux∗(0)=0.01137\nu u^*_x(0)=0.01137(N=4096N=4096 时为 0.01137)。解仍然收敛,但只有一阶:错误版本相当于把面 0 的黏性导数加倍,状态在入口附近整体平移了 −h2ux∗(0)-\tfrac h2u^*_x(0)——N=4096N=4096 时 (U1−u∗(x1))/(h ux∗(0))(U_1-u^*(x_1))/(h\,u^*_x(0)):本页 6×10−66\times10^{-6},错误版本 −0.496。

R~1\tilde R_1 is inconsistent: with the exact nodal values inserted, the page's R1R_1 is O(h2)O(h^2) (R1/h2=−1.224R_1/h^2=−1.224 at N=4096N=4096; the interior rows are O(h3)O(h^3)), while the slip's R~1\tilde R_1 tends to the constant νux∗(0)=0.01137\nu u^*_x(0)=0.01137 (0.01137 at N=4096N=4096). The solution still converges, but only at first order: the slip doubles the viscous derivative at face 0 and the state near the inlet is displaced as a whole by −h2ux∗(0)-\tfrac h2u^*_x(0): at N=4096N=4096, (U1−u∗(x1))/(h ux∗(0))(U_1-u^*(x_1))/(h\,u^*_x(0)) is 6×10−66\times10^{-6} for the page and −0.496 for the slip.

图 97 · 本页(实线)与错误版本(虚线),无限制器线性重构。(a) 状态 L1 误差与 dJ_h/ da 的误差:错误版本在每个网格上都更大,N=8 到 64 时状态误差是本页的 1.6 到 35 倍,a 分量的梯度误差是 3.8 到 41 倍,容易被当作“粗网格误差”,之后只按一阶收敛;N=4096 时状态误差是本页的 3513 倍,a 分量的梯度误差是 16318 倍。(b) 乘子之比 ψ_0νλ_x(0)(紫):本页和错误版本都趋于 1;斜率比 (ψ_1/h)λ_x(0)(红):本页趋于 1,错误版本趋于 0.501,即 1/2。实线:本页(所有面距离 h)虚线:错误版本(边界面距离 h/2)(a) 状态 L1 误差(a) dJh​/da 的误差(b) 紫:ψ0​ ÷ (ν λx​(0))(b) 红:(ψ1​/h) ÷ λx​(0)10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​1101001000N误差(a) 状态 L1 误差与 dJh​/da 的误差hh2​00.250.50.751101001000N(b) 与连续值之比
图 97 · 本页(实线)与错误版本(虚线),无限制器线性重构。(a) 状态 L1 误差与 dJh/da\mathrm dJ_h/\mathrm da 的误差:错误版本在每个网格上都更大,N=8N=8 到 64 时状态误差是本页的 1.6 到 35 倍,aa 分量的梯度误差是 3.8 到 41 倍,容易被当作“粗网格误差”,之后只按一阶收敛;N=4096N=4096 时状态误差是本页的 3513 倍,aa 分量的梯度误差是 16318 倍。(b) 乘子之比 ψ0÷νλx(0)\psi_0\div\nu\lambda_x(0)(紫):本页和错误版本都趋于 1;斜率比 (ψ1/h)÷λx(0)(\psi_1/h)\div\lambda_x(0)(红):本页趋于 1,错误版本趋于 0.501,即 1/2。
Figure 97 · The page (solid) and the slip (dashed), unlimited linear reconstruction. (a) The state L1 error and the error of dJ_h/ da: the slip is larger on every mesh: at N=8 to 64 its state error is 1.6 to 35 times the page's and its a-gradient error 3.8 to 41 times, easily mistaken for a “coarse-mesh error”, and after that it converges at first order only; at N=4096 the slip's state error is 3513 times the page's and its a-gradient error 16318 times. (b) The multiplier ratio ψ_0νλ_x(0) (violet): the page and the slip both tend to 1; the slope ratio (ψ_1/h)λ_x(0) (red): the page tends to 1, the slip to 0.501, that is 1/2.solid: the page (every face at distance h)dashed: the slip (boundary faces at distance h/2)(a) state L1 error(a) error of dJh​/da(b) violet: ψ0​ ÷ (ν λx​(0))(b) red: (ψ1​/h) ÷ λx​(0)10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​1101001000Nerror(a) state L1 error and the error of dJh​/dahh2​00.250.50.751101001000N(b) ratios to the continuous values
Figure 97 · The page (solid) and the slip (dashed), unlimited linear reconstruction. (a) The state L1 error and the error of dJh/da\mathrm dJ_h/\mathrm da: the slip is larger on every mesh: at N=8N=8 to 64 its state error is 1.6 to 35 times the page's and its aa-gradient error 3.8 to 41 times, easily mistaken for a “coarse-mesh error”, and after that it converges at first order only; at N=4096N=4096 the slip's state error is 3513 times the page's and its aa-gradient error 16318 times. (b) The multiplier ratio ψ0÷νλx(0)\psi_0\div\nu\lambda_x(0) (violet): the page and the slip both tend to 1; the slope ratio (ψ1/h)÷λx(0)(\psi_1/h)\div\lambda_x(0) (red): the page tends to 1, the slip to 0.501, that is 1/2.

教训有三条。第一,粗网格上看不出来:错误版本在 N=8N=8 到 16 时的状态误差只是本页的 1.6 到 3.7 倍;把收敛阶测到足够细才暴露它:N=16N=16 到 128 之间状态误差的阶只有 0.26 到 0.74,最细两层之间 1.00,梯度 1.00,而本页是 2.00。第二,核心结果也看不出来:乘子 ψ0÷νλx(0)\psi_0\div\nu\lambda_x(0) 在错误版本里同样趋于 1(N=8N=8 时 0.9922,N=4096N=4096 时 0.99997)——因为乘子由第 0 行的通量收支决定,而这个收支在错误版本里仍然成立;斜率比 (ψ1/h)÷λx(0)→1/2(\psi_1/h)\div\lambda_x(0)\to1/2 才直接显示第一个区间里伴随的斜率少了一半。第三,错误版本自己的切线、伴随和点积检验都完全正确,dJh/dD\mathrm dJ_h/\mathrm dD 的伴随值与切线值、复数步长值一致——它们检验的是程序的导数,而不检验程序离散的究竟是哪个方程。

Three lessons. First, it is invisible on coarse meshes: at N=8N=8 to 16 the slip's state error is only 1.6 to 3.7 times the page's; it shows up when the order is measured far enough: between N=16N=16 and 128 the state-error order is only 0.26 to 0.74, between the two finest levels 1.00 and for the gradient 1.00, against 2.00 for the page. Second, the central result does not see it either: the multiplier ratio ψ0÷νλx(0)\psi_0\div\nu\lambda_x(0) tends to 1 for the slip too (0.9922 at N=8N=8, 0.99997 at N=4096N=4096), because the multiplier is fixed by the flux balance of row 0 and that balance still holds in the slip; it is the slope ratio (ψ1/h)÷λx(0)→1/2(\psi_1/h)\div\lambda_x(0)\to1/2 that shows directly that the slope of the adjoint in the first interval is halved. Third, the slip's own tangent, adjoint and dot test are all perfectly right and its adjoint and tangent values of dJh/dD\mathrm dJ_h/\mathrm dD agree with each other and with complex step: they test the derivative of the program, not which equation the program discretises.

本节测到的:内部节点上 ψj→λ(xj)\psi_j\to\lambda(x_j)(无限制器线性二阶、一阶格式一阶),两个约束行的乘子 ψ0→νλx(0)\psi_0\to\nu\lambda_x(0)、ψN→−νλx(1)\psi_N\to-\nu\lambda_x(1)(同阶),离散梯度连同源项部分与边界部分都趋于连续值。但在粗网格上,梯度虽是 Jh(D)J_h(D) 的导数(精确到舍入误差),却离连续梯度很远(N=16N=16 时 aa、φ\varphi 分量分别差 10% 与 93%,N=64N=64 时差 0.8% 与 3.1%;N<91N<91 时层没被分辨):N=8N=8 时 dJh/dφ=0.420\mathrm dJ_h/\mathrm d\varphi=0.420,连续值为 0.085。本页格式的误差一部分来自出口乘子和入口附近节点的 O(1)O(1) 偏差,一部分来自目标的梯形公式(见上面的分解)。边界斜率的作用很大(没有它们 aa 分量的误差约为本页的 20 倍),但本页自身的粗网格误差有多少来自边界面,这里没有分离;这些都只是本问题上的数值证据。

What this section measured: ψj→λ(xj)\psi_j\to\lambda(x_j) at the interior nodes (second order for unlimited linear, first order for the first-order scheme), the multipliers of the two constraint rows tend to νλx(0)\nu\lambda_x(0) and −νλx(1)-\nu\lambda_x(1) (at the same order), and the discrete gradient, with its source part and its boundary parts, tends to the continuous values. But on coarse meshes the gradient, although it is the derivative of Jh(D)J_h(D), exact up to rounding, is far from the continuous one (at N=16N=16 the aa and φ\varphi components are off by 10% and 93%, at N=64N=64 by 0.8% and 3.1%; the layer is unresolved for N<91N<91): dJh/dφ=0.420\mathrm dJ_h/\mathrm d\varphi=0.420 against 0.085 at N=8N=8. The error of the page's scheme comes partly from the outlet multiplier and the O(1)O(1) deviation of the nodes next to the inlet, partly from the trapezoid rule of the objective (the budgets above). The boundary slopes matter a great deal (without them the aa component is 20 times worse), but how much of the page's own coarse-mesh error is due to its boundary faces is not isolated here; all of this is numerical evidence for this one problem.

第 17 节Section 17

GS 与 GMRES:迭代及其转置

GS and GMRES: the iterations and their transposes

本节实验:先估计一下,N=64N=64 时(无限制器线性)切线方程的 GS 要迭代多少次?伴随方程是否一样多?然后用本节的收敛面板验证。

Experiment: Estimate first how many GS iterations the tangent system needs at N=64N=64 (unlimited linear), and whether the adjoint system needs the same number. Then check with the convergence panel of this section.

第 10 节和第 11 节用 LU 解 Avk=−RDekAv_k=-R_De_k 与 ATψ=−gA^T\psi=-g。全局控件的网格很小,模型直接分解稠密矩阵;第 16、17 节的面板用带状 LU:AA 只有五条带(N+1N+1 个节点未知量),分解和回代都是 O(N)O(N)。二维、三维问题里直接分解会产生大量填充,迭代法取而代之。本节为本页自己的两个方程构造两种迭代,如实测量它们,并说明对伴随最重要的结构:伴随迭代是切线迭代的转置。

Section 10 and Section 11 solve Avk=−RDekAv_k=-R_De_k and ATψ=−gA^T\psi=-g with LU. The meshes of the global controls are small and the model factors the dense matrix; the panels of Sections 16 and 17 use a band LU: AA has only five bands (on the N+1N+1 nodal unknowns), so factorisation and solution cost O(N)O(N). In two and three dimensions a direct factorisation fills in and iterations take over. This section builds two iterations for the page's own two systems, measures them honestly, and shows the structure that matters most for adjoints: the adjoint iteration is the transpose of the tangent iteration.

两个方程与直接解法

The two systems and the direct solve

两个方程都写成 Kx=bKx=b:切线方程取 K=AK=A、b=−RDekb=-R_De_k、x=vkx=v_k;伴随方程取 K=ATK=A^T、b=−gb=-g、x=ψx=\psi。本节里 xx 只表示这个未知向量,不表示坐标,KK 也与第 8 节的 KfK_f 无关;结论里的 μ\mu 是 BABA 的特征值,不是第 16 节的乘子 μ0\mu_0。

Both systems are written Kx=bKx=b: the tangent system has K=AK=A, b=−RDekb=-R_De_k, x=vkx=v_k; the adjoint system K=ATK=A^T, b=−gb=-g, x=ψx=\psi. In this section xx is only this unknown vector, never the coordinate, and KK has nothing to do with the KfK_f of Section 8; the μ\mu of the conclusions is an eigenvalue of BABA, not the multiplier μ0\mu_0 of Section 16.

Kx=b,(K, b, x)∈{(A, −RDek, vk), (AT, −g, ψ)}.Kx=b,\qquad (K,\,b,\,x)\in\bigl\{(A,\,-R_De_k,\,v_k),\ (A^T,\,-g,\,\psi)\bigr\}.

AA 有两条下带、两条上带(一阶格式各一条):一个面的通量涉及 Uf−1,…,Uf+2U_{f-1},\dots,U_{f+2},一行用两个面。整条带只要前向代码的五次乘积,而不是 N+1N+1 次:每个种子是每隔五列取一列的单位向量 eje_j 之和(按 jj 除以 5 的余数分成五组);同一种子所含各列在任一行中都不会同时有非零元,所以每次乘积给出带的五分之一(核对:与模型逐列求出的 Jacobian 完全相同,差为 0)。部分选主元的 LU 分解仍保持带状(行交换另需两条上带):N=128N=128(129 个未知量)时分解加一次回代共 1906 次运算(乘加 1522 次、除法 384 次,行交换 127 次),每个未知量约 14.8 次;伴随方程分解 ATA^T,代价相近(同一个 NN:1651 次运算,乘加 1267 次、除法 384 次,行交换 0 次)。

AA has two sub- and two superdiagonals (one each at first order): the flux of a face involves Uf−1,…,Uf+2U_{f-1},\dots,U_{f+2} and a row uses two faces. The whole band takes five products of the tangent code, not N+1N+1: each seed is the sum of the unit vectors eje_j of every fifth column (one seed per residue of jj modulo 5); the columns summed in one seed never both have a nonzero in the same row, so each product delivers a fifth of the band (checked: identical to the model's column-by-column Jacobian, difference 0). LU with partial pivoting keeps the band (the row interchanges need two more superdiagonals): at N=128N=128 (129 unknowns) factorisation and one solve take 1906 operations (1522 multiply-adds and 384 divisions, with 127 row interchanges), about 14.8 per unknown; the adjoint factorises ATA^T at a similar cost (the same NN: 1651 operations, 1267 multiply-adds and 384 divisions, with 0 row interchanges).

格点格式还有一个格心页没有的结构:第 0 行和第 NN 行是约束行(单位行),所以 A0j=0A_{0j}=0(j≥1j\ge1)、ANj=0A_{Nj}=0(j<Nj<N)。按(节点 0|内部节点 1,…,N−11,\dots,N-1|节点 NN)分块,

The node scheme has a structure the cell-centred page lacks: rows 0 and NN are the constraint rows (unit rows), so A0j=0A_{0j}=0 (j≥1j\ge1) and ANj=0A_{Nj}=0 (j<Nj<N). Blocked as (node 0 | interior nodes 1,…,N−11,\dots,N-1 | node NN),

A=(100AI0AIIAIN001),AT=(1AI0T00AIIT00AINT1).A=\begin{pmatrix}1&0&0\\ A_{I0}&A_{II}&A_{IN}\\ 0&0&1\end{pmatrix},\qquad A^T=\begin{pmatrix}1&A_{I0}^T&0\\ 0&A_{II}^T&0\\ 0&A_{IN}^T&1\end{pmatrix}.

切线方程由边界数据驱动:v0=b0v_0=b_0、vN=bNv_N=b_N,然后 AIIvI=bI−AI0v0−AINvNA_{II}v_I=b_I-A_{I0}v_0-A_{IN}v_N。伴随方程在内部是封闭的:AIITψI=−wIA_{II}^T\psi_I=-w_I,两个乘子随后由第 0 行和第 NN 行读出,ψ0=−w0−AI0TψI\psi_0=-w_0-A_{I0}^T\psi_I、ψN=−wN−AINTψI\psi_N=-w_N-A_{IN}^T\psi_I。这和第 16 节的行 0 收支是同一件事。本页在 N=16N=16 上核对了这两个分块算法:相对完整求解,差不超过 10−1310^{-13}。迭代只在内部块上做实事:切线迭代里两个单位行第一次扫描就解完了;伴随迭代里两个乘子由内部值算出,并不反馈给内部。内部块单独迭代的谱半径与整个迭代的谱半径相差不超过 10−810^{-8}。

The tangent system is driven by the boundary data: v0=b0v_0=b_0, vN=bNv_N=b_N, then AIIvI=bI−AI0v0−AINvNA_{II}v_I=b_I-A_{I0}v_0-A_{IN}v_N. The adjoint system is closed in the interior: AIITψI=−wIA_{II}^T\psi_I=-w_I, and the two multipliers follow from rows 0 and NN, ψ0=−w0−AI0TψI\psi_0=-w_0-A_{I0}^T\psi_I, ψN=−wN−AINTψI\psi_N=-w_N-A_{IN}^T\psi_I: this is the row-0 balance of Section 16. This page checks the two blocked algorithms at N=16N=16 against the full solves, to within 10−1310^{-13}. An iteration has real work to do only on the interior block: in the tangent iteration the two unit rows are solved by the first sweep; in the adjoint iteration the two multipliers are computed from the interior values and do not feed back into it. The spectral radius of the iteration on the interior block alone differs from that of the whole iteration by less than 10−810^{-8}.

以一阶 Jacobian 作预处理的 GS 缺陷校正

GS defect correction with the first-order Jacobian

设 PP 是一阶残差在同一状态处的 Jacobian(三条带,两个约束行与 AA 的相同;一阶格式时 P=AP=A)。在 Pz=rPz=r 上从零出发做一次 GS 扫描,按节点顺序依次求出(单位行给出 z0=r0z_0=r_0 和 zN=rNz_N=r_N):

Let PP be the Jacobian of the first-order residual at the same state (three bands, the two constraint rows as in AA; P=AP=A for the first-order scheme). One GS sweep from zero on Pz=rPz=r runs through the nodes in order (the unit rows give z0=r0z_0=r_0 and zN=rNz_N=r_N):

zi=1Pii(ri−∑j<iPij zj),i=0,1,…,N;z=Br,B=(diag⁡P+LP)−1,z_i=\frac{1}{P_{ii}}\Bigl(r_i-\sum_{j<i}P_{ij}\,z_j\Bigr),\quad i=0,1,\dots,N;\qquad z=Br,\qquad B=(\operatorname{diag}P+L_P)^{-1},

LPL_P 是 PP 的严格下三角部分,zz 是扫描的输出(不是第 1 节的相位 zz)。缺陷校正把扫描 BB 作用在精确算子的残差上:

with LPL_P the strictly lower part of PP and zz the output of the sweep (not the phase zz of Section 1). The defect correction applies the sweep BB to the residual of the exact operator:

Δxm=ω B (b−Kxm),xm+1=xm+Δxm,x0=0.\Delta x^m=\omega\,B\,(b-Kx^m),\qquad x^{m+1}=x^m+\Delta x^m,\qquad x^0=0.

减去精确解 xx:误差满足 xm+1−x=(I−ωBA)(xm−x)x^{m+1}-x=(I-\omega BA)(x^m-x)(切线方程)。对任意初值收敛当且仅当误差传播矩阵的谱半径 ρ(I−ωBA)<1\rho(I-\omega BA)<1;进入渐近阶段后,误差每迭代一次约乘以 ρ\rho。迭代只需要 KxKx:按无矩阵(matrix-free)方式实现时,切线方程用第 8 节的 residual_d,伴随方程用第 9 节的 residual_b;需要存储的只有 PP 的三条带。

Subtract the solution xx: the error obeys xm+1−x=(I−ωBA)(xm−x)x^{m+1}-x=(I-\omega BA)(x^m-x) (tangent system). The iteration converges from every start exactly when the spectral radius of the error propagation matrix is below one, ρ(I−ωBA)<1\rho(I-\omega BA)<1; once the asymptotic phase is reached, every iteration multiplies the error by about ρ\rho. The iteration needs only products KxKx: implemented matrix-free, the tangent system uses residual_d of Section 8 and the adjoint system residual_b of Section 9; only the three bands of PP are stored.

伴随迭代是切线迭代的转置

The adjoint iteration is the transpose of the tangent iteration

从零出发做 mm 次切线迭代,结果对 bb 是线性的:

Run the tangent iteration mm times from zero; the result is linear in bb:

xm=ℳm b,ℳm=∑k=0m−1(I−ωBA)k ωB.x^m=\mathcal M_m\,b,\qquad \mathcal M_m=\sum_{k=0}^{m-1}(I-\omega BA)^k\,\omega B.

逐项转置,并把 BTB^T 穿过幂次(BT(ATBT)k=(BTAT)kBTB^T(A^TB^T)^k=(B^TA^T)^kB^T):

Transpose term by term and move BTB^T through the power (BT(ATBT)k=(BTAT)kBTB^T(A^TB^T)^k=(B^TA^T)^kB^T):

ℳmT=∑k=0m−1ωBT(I−ωATBT)k=∑k=0m−1(I−ωBTAT)k ωBT.\mathcal M_m^T=\sum_{k=0}^{m-1}\omega B^T\bigl(I-\omega A^TB^T\bigr)^k=\sum_{k=0}^{m-1}\bigl(I-\omega B^TA^T\bigr)^k\,\omega B^T.

这正是伴随方程迭代 ψm+1=ψm+ωBT(b−ATψm)\psi^{m+1}=\psi^m+\omega B^T(b-A^T\psi^m) 的 mm 步映射。而 BT=(diag⁡P+LPT)−1B^T=(\operatorname{diag}P+L_P^T)^{-1}:解 (diag⁡P+LPT)z=r(\operatorname{diag}P+L_P^T)z=r 从最后一个节点开始,

This is the mm-step map of the adjoint iteration ψm+1=ψm+ωBT(b−ATψm)\psi^{m+1}=\psi^m+\omega B^T(b-A^T\psi^m). And BT=(diag⁡P+LPT)−1B^T=(\operatorname{diag}P+L_P^T)^{-1}: solving (diag⁡P+LPT)z=r(\operatorname{diag}P+L_P^T)z=r starts from the last node,

zi=1Pii(ri−∑j>iPji zj),i=N,N−1,…,1,0,z_i=\frac{1}{P_{ii}}\Bigl(r_i-\sum_{j>i}P_{ji}\,z_j\Bigr),\quad i=N,N-1,\dots,1,0,

即在 PTP^T 上反向扫描:zN=rNz_N=r_N 先出,内部节点从 N−1N-1 往下,最后 z0=r0−∑j>0Pj0zjz_0=r_0-\sum_{j>0}P_{j0}z_j 用刚算出的内部值给出入口乘子——和上面的分块算法一致。由此得到四个结论,都已测量:

a backward sweep on PTP^T: zN=rNz_N=r_N comes first, the interior nodes follow from N−1N-1 downwards, and last z0=r0−∑j>0Pj0zjz_0=r_0-\sum_{j>0}P_{j0}z_j uses the freshly computed interior values to give the inlet multiplier, as the blocked algorithm above does. Four consequences, all measured:

  • 迭代的点积检验。对任意 bb、b′b' 和每个 mm,b′T(ℳmb)=(ℳmTb′)Tbb'^T(\mathcal M_mb)=(\mathcal M_m^Tb')^Tb。随机的 b,b′b,b'(N=16N=16,m=1,…,60m=1,\dots,60)测得最大相对差不超过 10−1410^{-14};Python 审计显式构造两个 mm 步矩阵(m≤20m\le20,N=8,16,32N=8,16,32,三种重构),差同样在舍入误差量级。Dot test of the iterations. b′T(ℳmb)=(ℳmTb′)Tbb'^T(\mathcal M_mb)=(\mathcal M_m^Tb')^Tb for all bb, b′b' and every mm. With random b,b′b,b' (N=16N=16, m=1,…,60m=1,\dots,60) the largest relative difference is below 10−1410^{-14}; the Python audit forms both mm-step matrices explicitly (m≤20m\le20, N=8,16,32N=8,16,32, three reconstructions) and finds differences at the level of rounding.
  • 截断的梯度在每一步都相等。令 vkm=ℳm(−RDek)v_k^m=\mathcal M_m(-R_De_k)、ψm=ℳmT(−g)\psi^m=\mathcal M_m^T(-g),则 wTvkm=−(ℳmTw)TRDekw^Tv_k^m=-(\mathcal M_m^Tw)^TR_De_k,也就是 (ψm)TRDek(\psi^m)^TR_De_k:切线 GS 与伴随 GS 迭代 mm 次后给出同一个导数,此时两者都还没收敛(图 98,最大差不超过 10−1410^{-14})。The truncated gradients agree at every step. With vkm=ℳm(−RDek)v_k^m=\mathcal M_m(-R_De_k) and ψm=ℳmT(−g)\psi^m=\mathcal M_m^T(-g), wTvkm=−(ℳmTw)TRDekw^Tv_k^m=-(\mathcal M_m^Tw)^TR_De_k, which is (ψm)TRDek(\psi^m)^TR_De_k: tangent GS and adjoint GS give the same derivative after mm iterations, while neither has converged (Figure 98, largest difference below 10−1410^{-14}).
  • 转置的扫描是反向的。伴随把信息从出口带向入口(第 16 节),反向扫描顺着这个方向。在 PTP^T 上做前向扫描也是伴随方程的一种合法迭代,但它不是切线迭代的转置。粗网格上它慢得多(N=16N=16:261 次,转置迭代 71 次),但网格 Péclet 数 uinh/νu_{\rm in}h/\nu 降到约 1.5 以下后就不再如此(N=64N=64:前向扫描 268 次,转置迭代 267 次;N=512N=512:前向扫描 7882 次,转置迭代 7515 次;光滑限制器在 N=64N=64 时前向扫描反而更快:278 次,转置迭代 295 次)。The transposed sweep runs backward. The adjoint carries information from the outlet to the inlet (Section 16), and the backward sweep follows that direction. A forward sweep on PTP^T is also a valid iteration for the adjoint system, but it is not the transpose of the tangent iteration. On coarse meshes it is much slower (N=16N=16: 261 iterations against 71 for the transposed one), but not once the mesh Péclet number uinh/νu_{\rm in}h/\nu drops below about 1.5 (N=64N=64: forward sweep 268, transposed 267; N=512N=512: forward sweep 7882, transposed 7515; with the smooth limiter at N=64N=64 the forward sweep is even faster: 278 against 295 for the transposed one).
  • 同样的渐近速度。I−ωBTAT=BT(I−ωBA)TB−TI-\omega B^TA^T=B^T(I-\omega BA)^TB^{-T} 与 (I−ωBA)T(I-\omega BA)^T 相似,所以两个误差传播矩阵的特征值相同;测得的谱半径相差不超过 10−810^{-8}(受舍入误差限制:在双精度下,这类非对称矩阵的特征值只能算到这个精度,numpy 的 LAPACK 给出同类的差别)。迭代次数仍可略有不同(右端项不同,见下表)。The same asymptotic rate. I−ωBTAT=BT(I−ωBA)TB−TI-\omega B^TA^T=B^T(I-\omega BA)^TB^{-T} is similar to (I−ωBA)T(I-\omega BA)^T, so the two error propagation matrices have the same eigenvalues; the measured spectral radii differ by less than 10−810^{-8} (limited by rounding: in double precision the eigenvalues of such non-symmetric matrices cannot be computed more accurately, and numpy's LAPACK shows differences of the same kind). The iteration counts can still differ a little (different right-hand sides; table below).
图 98 · 迭代 m 次后的导数 dJ_h/ da(无限制器线性,N=16)。切线 GS 的 w^Tv^m(粗线)与伴随 GS 的 (ψ^m)^TR_De_0(点)在每一步重合;切线与伴随 GMRES(虚线)在收敛前不同,只在收敛后一致;点线是收敛值 −0.1301。切线 GS:wT​ vm​伴随 GS:(ψm​)T​ RD​ e0​切线 GMRES伴随 GMRES收敛值−0.4−0.3−0.2−0.100.10510152025303540迭代次数 mdJh​/da
图 98 · 迭代 mm 次后的导数 dJh/da\mathrm dJ_h/\mathrm da(无限制器线性,N=16N=16)。切线 GS 的 wTvmw^Tv^m(粗线)与伴随 GS 的 (ψm)TRDe0(\psi^m)^TR_De_0(点)在每一步重合;切线与伴随 GMRES(虚线)在收敛前不同,只在收敛后一致;点线是收敛值 −0.1301。
Figure 98 · The derivative dJ_h/ da after m iterations (unlimited linear, N=16). The tangent GS value w^Tv^m (thick) and the adjoint GS value (ψ^m)^TR_De_0 (dots) coincide at every step; the tangent and adjoint GMRES values (dashed) differ before convergence and agree only after it; dotted: the converged value −0.1301.tangent GS: wT​ vm​adjoint GS: (ψm​)T​ RD​ e0​tangent GMRESadjoint GMRESconverged value−0.4−0.3−0.2−0.100.10510152025303540iterations mdJh​/da
Figure 98 · The derivative dJh/da\mathrm dJ_h/\mathrm da after mm iterations (unlimited linear, N=16N=16). The tangent GS value wTvmw^Tv^m (thick) and the adjoint GS value (ψm)TRDe0(\psi^m)^TR_De_0 (dots) coincide at every step; the tangent and adjoint GMRES values (dashed) differ before convergence and agree only after it; dotted: the converged value −0.1301.

GMRES

GMRES

GMRES 保留已经产生的方向,把它们组合起来。用同一个扫描 BB 作右预处理,第 mm 步的近似解为

GMRES keeps the directions it has generated and combines them. Right-preconditioned with the same sweep BB, the mm-th approximation is

xm=B ym,ym=arg⁡min⁡y∈𝒦m∥b−KBy∥2,𝒦m=span⁡{b, KBb, …, (KB)m−1b},x^m=B\,y^m,\qquad y^m=\arg\min_{y\in\mathcal K_m}\|b-KBy\|_2,\qquad \mathcal K_m=\operatorname{span}\bigl\{b,\,KBb,\,\dots,\,(KB)^{m-1}b\bigr\},

用 Arnoldi 过程(修正 Gram–Schmidt 做两遍)和 Givens 旋转计算;本页每一步都记录真实残差 ∥b−Kxm∥2\|b-Kx^m\|_2。重启版本每走固定步数(5、10 或 30 步)就从当前解重新开始,以限制存储。伴随版本用 K=ATK=A^T 与 BTB^T。由定义可得两点:不重启时 GMRES 至多 N+1N+1 步(方程的维数)就得到精确解(测量:N=8N=8 时 8 步,N=16N=16 时 16 步);GMRES 对 bb 不是线性的,ymy^m 通过极小化依赖 bb,所以没有 GS 那样的 mm 步转置:切线与伴随 GMRES 的导数在收敛前不同(N=16N=16、m≤6m\le6 时差可达 0.237),收敛后才一致(差不超过 10−1410^{-14})。

computed with the Arnoldi process (modified Gram–Schmidt, two passes) and Givens rotations; the page records the true residual ∥b−Kxm∥2\|b-Kx^m\|_2 after every step. The restarted versions start again from the current iterate after a fixed number of steps (5, 10 or 30) to bound the storage. The adjoint version uses K=ATK=A^T and BTB^T. Two facts follow from the definition: without restarts GMRES reaches the exact solution in at most N+1N+1 steps (the dimension of the system; measured: 8 steps at N=8N=8, 16 at N=16N=16); and GMRES is not linear in bb, since ymy^m depends on bb through the minimisation, so there is no mm-step transposition as for GS: the tangent and adjoint GMRES derivatives differ before convergence (up to 0.237 for m≤6m\le6 at N=16N=16) and agree once both have converged (difference below 10−1410^{-14}).

测量:迭代次数、谱半径、代价

Measurements: iterations, spectral radius, cost

下表给出的是使 ∥b−Kxm∥2≤10−10∥b∥2\|b-Kx^m\|_2\le10^{-10}\|b\|_2 的迭代次数(“切线/伴随”,切线方程取 k=0k=0,即振幅 aa),无限制器线性重构,默认设计;GMRES(N+1N+1) 即不重启(至多 N+1N+1 步得到精确解),ω=0.65\omega=0.65 的次数见收敛面板;N=256N=256、512 只列重启的 GMRES。ρ\rho 是 I−BAI-BA 的谱半径,ln⁡10−10/ln⁡ρ\ln10^{-10}/\ln\rho 是由它预测的次数。Python 审计用自己的稠密 GS、GMRES(numpy)复现了每一个次数(重启的 GMRES 在 N≥128N\ge128 时相差不超过 2%),用 numpy 的特征值复现了每一个谱半径。

The table counts the iterations until ∥b−Kxm∥2≤10−10∥b∥2\|b-Kx^m\|_2\le10^{-10}\|b\|_2 (“tangent / adjoint”, the tangent system for k=0k=0, the amplitude aa), unlimited linear reconstruction, default design; GMRES(N+1N+1) is GMRES without restart (exact within N+1N+1 steps); the counts for ω=0.65\omega=0.65 are in the convergence panel; for N=256N=256 and 512 only the restarted GMRES is listed. ρ\rho is the spectral radius of I−BAI-BA, and ln⁡10−10/ln⁡ρ\ln10^{-10}/\ln\rho the count it predicts. The Python audit reproduces every count with its own dense GS and GMRES (numpy; the restarted GMRES within 2% for N≥128N\ge128) and every spectral radius with numpy's eigenvalues.

NGS ω=1\omega=1ω=0.8\omega=0.8ω=0.5\omega=0.5ρ\rholn⁡10−10/ln⁡ρ\ln10^{-10}/\ln\rhoGMRES(5)GMRES(10)GMRES(30)GMRES(N+1N+1)
852 / 5469 / 71118 / 1210.62114825 / 238 / 88 / 88 / 8
1670 / 7192 / 93155 / 1580.67405850 / 4242 / 3316 / 1616 / 16
32114 / 117148 / 152248 / 2550.75588268 / 6471 / 8029 / 2929 / 29
64256 / 267324 / 338529 / 5520.873517098 / 93124 / 12990 / 8848 / 45
128660 / 702829 / 8821337 / 14230.9478429159 / 133202 / 215270 / 41786 / 81
256282 / 278375 / 280670 / 646
5121176 / 915687 / 671961 / 838

三种重构对比(GS,ω=1\omega=1,切线/伴随,以及 ρ\rho):

The three reconstructions side by side (GS, ω=1\omega=1, tangent / adjoint, and ρ\rho):

N一阶first无限制器none光滑smoothρ\rho(一阶)ρ\rho (first)ρ\rho(无限制器)ρ\rho (none)ρ\rho(光滑)ρ\rho (smooth)
877 / 8052 / 5463 / 660.74960.62110.6819
16117 / 13270 / 7179 / 820.83610.67400.7338
32197 / 209114 / 117119 / 1230.88680.75580.7757
64373 / 388256 / 267283 / 2950.93130.87350.9001
128851 / 890660 / 702754 / 7930.96560.94780.9599
图 99 · 迭代次数随 N 的变化(切线方程,分量 a,默认设计)。从 N=32 起(网格 Péclet 数 u_inh/ν ≤ 2.86),GS 的迭代次数增长得比 N 快:无限制器线性从 N=32 的 114 次、N=64 的 256 次到 N=512 的 6750 次;紫线是 h=ν/u_in(网格 Péclet 数为 1);GMRES 次数少得多:N=512 时 GMRES(30) 要 961 次,GS 要 6750 次。点线:A 的带状 LU(分解加一次回代)的运算次数折合成 GS 迭代,约 1.8 次;A^T 约 1.6 次,离这条线很近。GS(一阶)GS(无限制器)GS(光滑)GMRES(30)(无限制器)GMRES 不重启(无限制器)A 的带状 LU 的代价(折合成 GS 迭代)110102​103​104​10100区间数 N迭代次数(切线方程,分量 a)h = ν/uin​NN2​
图 99 · 迭代次数随 NN 的变化(切线方程,分量 aa,默认设计)。从 N=32N=32 起(网格 Péclet 数 uinh/ν≤2.86u_{\rm in}h/\nu\le2.86),GS 的迭代次数增长得比 NN 快:无限制器线性从 N=32N=32 的 114 次、N=64N=64 的 256 次到 N=512N=512 的 6750 次;紫线是 h=ν/uinh=\nu/u_{\rm in}(网格 Péclet 数为 1);GMRES 次数少得多:N=512N=512 时 GMRES(30) 要 961 次,GS 要 6750 次。点线:AA 的带状 LU(分解加一次回代)的运算次数折合成 GS 迭代,约 1.8 次;ATA^T 约 1.6 次,离这条线很近。
Figure 99 · Iterations against N (tangent system, component a, default design). From N=32 on (mesh Péclet number u_inh/ν ≤ 2.86) the GS count grows faster than N: from 114 at N=32 and 256 at N=64 to 6750 at N=512 for unlimited linear; the violet line marks h=ν/u_in (mesh Péclet number 1); GMRES needs far fewer: 961 for GMRES(30) at N=512 against 6750 for GS. Dotted: the operations of the band LU of A (factorisation and one solve) expressed in GS iterations, about 1.8; for A^T about 1.6, close to this line.GS firstGS noneGS smoothGMRES(30) noneGMRES no restart, nonecost of the band LU of A (in GS iterations)110102​103​104​10100intervals Niterations (tangent, component a)h = ν/uin​NN2​
Figure 99 · Iterations against NN (tangent system, component aa, default design). From N=32N=32 on (mesh Péclet number uinh/ν≤2.86u_{\rm in}h/\nu\le2.86) the GS count grows faster than NN: from 114 at N=32N=32 and 256 at N=64N=64 to 6750 at N=512N=512 for unlimited linear; the violet line marks h=ν/uinh=\nu/u_{\rm in} (mesh Péclet number 1); GMRES needs far fewer: 961 for GMRES(30) at N=512N=512 against 6750 for GS. Dotted: the operations of the band LU of AA (factorisation and one solve) expressed in GS iterations, about 1.8; for ATA^T about 1.6, close to this line.
图 100 · (a) N=32 时 GS 误差传播矩阵 I-BA 的特征值都在单位圆内(无限制器线性:圆点,虚线圆半径 ρ=0.7558;一阶:方块)。(b) 谱半径随 N 增大趋于 1:网格越细,GS 越慢。一阶无限制器光滑单位圆半径 ρ(无限制器)−1−0.500.51−1−0.500.51ReIm(a) I − BA 的特征值,N = 320.50.60.70.80.9110100Nρ(I − BA)(b) 谱半径随 N 的变化
图 100 · (a) N=32N=32 时 GS 误差传播矩阵 I−BAI-BA 的特征值都在单位圆内(无限制器线性:圆点,虚线圆半径 ρ=0.7558\rho=0.7558;一阶:方块)。(b) 谱半径随 NN 增大趋于 1:网格越细,GS 越慢。
Figure 100 · (a) At N=32 every eigenvalue of the GS error propagation matrix I-BA lies inside the unit circle (unlimited linear: dots, dashed circle of radius ρ=0.7558; first order: squares). (b) The spectral radius tends to 1 as N grows: the finer the mesh, the slower GS.firstnonesmoothunit circleradius ρ (none)−1−0.500.51−1−0.500.51ReIm(a) eigenvalues of I − BA, N = 320.50.60.70.80.9110100Nρ(I − BA)(b) spectral radius against N
Figure 100 · (a) At N=32N=32 every eigenvalue of the GS error propagation matrix I−BAI-BA lies inside the unit circle (unlimited linear: dots, dashed circle of radius ρ=0.7558\rho=0.7558; first order: squares). (b) The spectral radius tends to 1 as NN grows: the finer the mesh, the slower GS.

结论(测量,不是定理):(1) GS 在测到的所有情形都收敛,但慢,而且网格越细越慢:无限制器线性 ρ\rho 从 0.621(N=8N=8)升到 0.948(N=128N=128),次数从 52 升到 660。(2) 欠松弛在这里没有帮助:设 μ\mu 是 BABA 中使 ∣1−μ∣|1-\mu| 最大的特征值,即 ρ(1)=∣1−μ∣\rho(1)=|1-\mu|。测得的所有情形里 ∣μ−12∣≤0.466|\mu-\tfrac12|\le0.466,即 μ\mu 都落在圆盘 ∣μ−12∣<12|\mu-\tfrac12|<\tfrac12 内;对这样的 μ\mu,∣1−ωμ∣|1-\omega\mu| 随 ω\omega 增大到 1 而减小,所以对每个 0<ω<10<\omega<1 有 ρ(ω)≥∣1−ωμ∣>ρ(1)\rho(\omega)\ge|1-\omega\mu|>\rho(1):欠松弛不可能减小 ρ\rho(在测到的情形里 ρ(ω)\rho(\omega) 在 ω\omega 从 1 降到 0.1 时还单调增大,步长取 0.05)。(3) ln⁡10−10/ln⁡ρ\ln10^{-10}/\ln\rho 给出量级。无限制器线性的实际次数总是更多(N=128N=128:预测 429,实测 660):开始的 300 次迭代里残差平均每次只乘以 0.983,最后 300 次才是 0.950(ρ=0.948\rho=0.948),预测忽略了渐近阶段之前的过渡。只有一阶格式的切线方程在 N=8N=8 与 16 时实测次数反而比预测略少(N=8N=8:实测 77,预测 80;N=16N=16:实测 117,预测 129),测量的 15 个情形里其余都更多。(4) GMRES 次数少得多(不重启时 N=128N=128 伴随 81 次)。重启后的迭代次数随重启长度的变化却不单调:N=128N=128 时伴随 GMRES(30) 要 417 次,比 GMRES(10) 的 215 次和 GMRES(5) 的 133 次都多,N=512N=512 时 GMRES(5) 又最慢(915 次,GMRES(10) 671 次);更长的重启不保证更快,这里只有不重启的 GMRES 稳妥(至多 N+1N+1 步)。(5) 代价:一次 GS 迭代约 8.0N8.0N 次运算,AA 的带状 LU 分解加回代约 14.8N14.8N(ATA^T:12.8N12.8N);GMRES 每一步再加上正交化,每个已存方向约 4N4N。一维问题里直接求解的代价只相当于约 1.8 次 GS 迭代(切线方程,AA)或约 1.6 次(伴随方程,ATA^T):这里讲迭代是为了它们的结构,以及二维、三维问题,而不是为了一维里的速度。

Conclusions (measured, not theorems): (1) GS converges in every case measured, but slowly, and the more slowly the finer the mesh: for unlimited linear ρ\rho rises from 0.621 (N=8N=8) to 0.948 (N=128N=128) and the count from 52 to 660. (2) Under-relaxation does not help here: let μ\mu be the eigenvalue of BABA with the largest ∣1−μ∣|1-\mu|, so that ρ(1)=∣1−μ∣\rho(1)=|1-\mu|. In every case measured ∣μ−12∣≤0.466|\mu-\tfrac12|\le0.466, so μ\mu lies in the disk ∣μ−12∣<12|\mu-\tfrac12|<\tfrac12; for such μ\mu, ∣1−ωμ∣|1-\omega\mu| decreases as ω\omega increases to 1, hence ρ(ω)≥∣1−ωμ∣>ρ(1)\rho(\omega)\ge|1-\omega\mu|>\rho(1) for every 0<ω<10<\omega<1: under-relaxation cannot reduce ρ\rho (in the cases measured ρ(ω)\rho(\omega) also increases monotonically as ω\omega falls from 1 to 0.1, in steps of 0.05). (3) ln⁡10−10/ln⁡ρ\ln10^{-10}/\ln\rho gives the order of magnitude. For unlimited linear the actual counts are always higher (at N=128N=128: 429 predicted, 660 measured): over the first 300 iterations the residual is multiplied on average by only 0.983 per iteration, over the last 300 by 0.950 (ρ=0.948\rho=0.948); the prediction ignores the transient before the asymptotic phase. Only the first-order scheme at N=8N=8 and 16 needs slightly fewer iterations than predicted for the tangent system (N=8N=8: 77 measured, 80 predicted; N=16N=16: 117 measured, 129 predicted); in the other 13 of the 15 cases measured the count is higher. (4) GMRES needs far fewer iterations (81 for the adjoint at N=128N=128 without restart). The restarted counts, however, are not monotone in the restart length: at N=128N=128 the adjoint GMRES(30) needs 417, more than GMRES(10) with 215 and GMRES(5) with 133, and at N=512N=512 GMRES(5) is the slowest (915, GMRES(10) 671); a longer restart guarantees nothing, and only unrestarted GMRES is dependable here (at most N+1N+1 steps). (5) Cost: a GS iteration takes about 8.0N8.0N operations, the band LU factorisation and solve of AA about 14.8N14.8N (ATA^T: 12.8N12.8N); a GMRES step adds the orthogonalisation, about 4N4N per stored direction. In one dimension the direct solve costs about 1.8 GS iterations (tangent system, AA) or about 1.6 (adjoint system, ATA^T): the iterations are taught here for their structure and for two and three dimensions, not for speed in one.

和格心页比较:同一设计下两种格式的 GS 次数几乎相同,例如无限制器线性 N=128N=128 的切线/伴随次数:节点 660 / 702,格心 642 / 704;谱半径 0.9478 与 0.9481。节点矩阵多出的两行(切线方程里的约束行,伴随方程里两个由内部值算出的乘子)与内部解耦,不改变渐近速度。

Compared with the cell-centred page: for the same design the two schemes need almost the same number of GS iterations, for instance unlimited linear at N=128N=128, tangent / adjoint: nodes 660 / 702, cells 642 / 704; spectral radius 0.9478 against 0.9481. The two extra rows of the node matrix (the constraint rows in the tangent system, the two multipliers computed from the interior in the adjoint system) decouple from the interior and do not change the asymptotic rate.

Nuinh/νu_{\rm in}h/\nu伴随:反向扫描(转置)adjoint: backward sweep (transpose)伴随:前向扫描adjoint: forward sweep
165.7271261
641.43267268
1280.71702689
2560.3621692288
5120.1875157882

不要把 GS 的“截断导数相等”套用到 GMRES 上:GS 的 mm 步映射是线性的,转置关系在每一步成立;GMRES 不是线性映射,只有收敛后的结果满足对偶关系。用迭代解求梯度时,切线与伴随的结果只能在收敛后比较(GMRES),或在相同 mm、严格转置的迭代之间比较(GS,此时应在舍入误差内一致);这时的差别指向导数代码或转置的错误。

Do not carry the “equal truncated derivatives” of GS over to GMRES: the mm-step map of GS is linear and the transposition holds at every step; GMRES is not a linear map, and only its converged results satisfy the duality. When gradients come from iterative solves, compare the tangent and adjoint values only at convergence (GMRES) or at equal mm with exactly transposed iterations (GS, where they must agree to rounding); a difference there points to an error in the derivative code or the transposition.

第 18 节Section 18

总结:一个网格、一个通量、三个方向

Summary: one mesh, one flux, three directions

本节实验:对三个方向,各说出种子是什么、解哪个方程、得到什么;然后用本节的总览面板核对——它对当前控件把所有计算重做一遍。

Experiment: For each of the three directions, say what is seeded, which equation is solved and what comes out. Then check with the dashboard of this section, which redoes every calculation for the current controls.

本页只算了一件事:离散目标 Jh(D)=wT𝐔(D)J_h(D)=w^T\mathbf U(D) 对设计 D=(a,φ,ν)D=(a,\varphi,\nu) 的导数。它用三种方式计算,三者共用网格、面通量和重构;变化的只是传播的数据和数据流的方向。

The page computed one thing, the derivative of the discrete objective Jh(D)=wT𝐔(D)J_h(D)=w^T\mathbf U(D) with respect to the design D=(a,φ,ν)D=(a,\varphi,\nu), in three ways that share the mesh, the face flux and the reconstruction; only the data that are propagated and the direction of the data flow change.

图 101 · 三个方向的数据流和本页的数字(默认设计,N=8,无限制器线性)。原始:设计 → Newton 法解出 U → J_h=1.463945。切线:每个种子 D-dot=e_k 一次线性求解,得 J-dot_k=w^Tv_k。伴随:从目标的种子出发,一次转置求解得到 ψ(包括两个约束行的乘子),再得 D-bar=R_D^Tψ,三个分量同时得到;切线与伴随的结果相差不超过 10^(-14)。原始D(0.2, 0.07, 0.01)R(U, D) = 0Newton 4 次U9 个节点值Jh​ = wT​ U1.463945切线D= ek​k = 0, 1, 2A vk​ = −RD​ ek​3 次线性求解vk​ =U3 × 9 个值Jk​= wT​ vk​(−0.1781, 0.4199, 0.0039)伴随D= RD​T​ ψ(−0.1781, 0.4199, 0.0039)ψ9 个值(含 ψ0​、ψN​)AT​ ψ = −g1 次线性求解J= 1, g = w目标的种子对偶:maxk​ |wT​ vk​ − ψT​ RD​ ek​| = 1.4e−15(N = 8,无限制器线性,默认设计)同一个网格、同一个面通量、同一个重构;变的只是数据和数据流的方向
图 101 · 三个方向的数据流和本页的数字(默认设计,N=8N=8,无限制器线性)。原始:设计 → Newton 法解出 𝐔\mathbf U → Jh=1.463945J_h=1.463945。切线:每个种子 D˙=ek\dot D=e_k 一次线性求解,得 J˙k=wTvk\dot J_k=w^Tv_k。伴随:从目标的种子出发,一次转置求解得到 ψ\psi(包括两个约束行的乘子),再得 Dˉ=RDTψ\bar D=R_D^T\psi,三个分量同时得到;切线与伴随的结果相差不超过 10−1410^{-14}。
Figure 101 · The data flow of the three directions with the page's numbers (default design, N=8, unlimited linear). Primal: design → Newton gives U → J_h=1.463945. Tangent: one linear solve per seed D-dot=e_k gives J-dot_k=w^Tv_k. Adjoint: from the seed of the objective, one transposed solve gives ψ (the multipliers of the two constraint rows included) and then D-bar=R_D^Tψ, all three components at once; the tangent and adjoint results differ by less than 10^(-14).PrimalD(0.2, 0.07, 0.01)R(U, D) = 0Newton, 4 iterationsU9 nodal valuesJh​ = wT​ U1.463945TangentD= ek​k = 0, 1, 2A vk​ = −RD​ ek​3 linear solvesvk​ =U3 × 9 valuesJk​= wT​ vk​(−0.1781, 0.4199, 0.0039)AdjointD= RD​T​ ψ(−0.1781, 0.4199, 0.0039)ψ9 values (ψ0​ and ψN​ included)AT​ ψ = −g1 linear solveJ= 1, g = wthe seed of the objectiveduality: maxk​ |wT​ vk​ − ψT​ RD​ ek​| = 1.4e−15 (N = 8, unlimited linear, default design)the same mesh, the same face flux, the same reconstruction; only the data and the direction of the data flow change
Figure 101 · The data flow of the three directions with the page's numbers (default design, N=8N=8, unlimited linear). Primal: design → Newton gives 𝐔\mathbf U → Jh=1.463945J_h=1.463945. Tangent: one linear solve per seed D˙=ek\dot D=e_k gives J˙k=wTvk\dot J_k=w^Tv_k. Adjoint: from the seed of the objective, one transposed solve gives ψ\psi (the multipliers of the two constraint rows included) and then Dˉ=RDTψ\bar D=R_D^T\psi, all three components at once; the tangent and adjoint results differ by less than 10−1410^{-14}.

三个方向

Three directions

原始Primal前向(tangent)Forward (tangent)伴随(adjoint)Reverse (adjoint)
种子SeedDDDDD˙=ek\dot D=e_k(𝐔˙=v\dot{\mathbf U}=v)D˙=ek\dot D=e_k (𝐔˙=v\dot{\mathbf U}=v)Rˉ=ψ\bar R=\psi(来自 Jˉ=1\bar J=1,g=wg=w)Rˉ=ψ\bar R=\psi (from Jˉ=1\bar J=1, g=wg=w)
运行的代码Code that runs残差代码(取值、重构、通量、分发)the residual code (gather, reconstruct, flux, scatter)residual_d,同序residual_d, same orderresidual_b,逆序,累加 +=residual_b, reverse order, accumulating +=
要解的方程Equation solvedR(𝐔,D)=0R(\mathbf U,D)=0(Newton 法)R(𝐔,D)=0R(\mathbf U,D)=0 (Newton)Avk=−RDekAv_k=-R_De_kAvk=−RDekAv_k=-R_De_kATψ=−gA^T\psi=-gATψ=−gA^T\psi=-g
输出Output𝐔\mathbf U,Jh=wT𝐔J_h=w^T\mathbf U𝐔\mathbf U, Jh=wT𝐔J_h=w^T\mathbf UJ˙k=gTvk\dot J_k=g^Tv_kJ˙k=gTvk\dot J_k=g^Tv_kDˉ=RDTψ\bar D=R_D^T\psi,以及乘子 ψ0,ψN\psi_0,\psi_NDˉ=RDTψ\bar D=R_D^T\psi, and the multipliers ψ0,ψN\psi_0,\psi_N
每个梯度的求解次数Solves per gradient——每个设计分量一次(3)one per design component (3)1(与分量个数无关)1 (any number of components)
本页位置Where第 5 节Section 5第 8 节、第 10 节Section 8, Section 10第 9 节、第 11 节、第 12 节Section 9, Section 11, Section 12

切线与伴随由对偶恒等式连在一起:对任意种子 RˉTR˙=𝐔ˉT𝐔˙+DˉTD˙\bar R^T\dot R=\bar{\mathbf U}^T\dot{\mathbf U}+\bar D^T\dot D(第 9 节的点积检验),在解上它变成 wTvk=ψTRDekw^Tv_k=\psi^TR_De_k。代价的差别也由此而来:切线每个设计分量要一次求解,伴随每个目标要一次求解;本页有 3 个分量、1 个目标。

The tangent and the adjoint are tied by the duality identity: RˉTR˙=𝐔ˉT𝐔˙+DˉTD˙\bar R^T\dot R=\bar{\mathbf U}^T\dot{\mathbf U}+\bar D^T\dot D for any seeds (the dot test of Section 9), which at the solution becomes wTvk=ψTRDekw^Tv_k=\psi^TR_De_k. The difference in cost comes from the same place: the tangent needs one solve per design component, the adjoint one solve per objective; this page has 3 components and 1 objective.

图 102 · 同一个面循环的三种用法。原始(蓝):重构面上的迹,算通量,分发到面两侧节点的对偶控制体(边界行是约束行,不参与分发)。切线(绿):按同样的顺序传播带点的量,用同样的重构权重和在原始迹处求得的 c_L,c_R,κ_f。伴随(红):从右向左,先从残差的种子取 H-bar_f=R-bar_f-R-bar_(f+1)(分发的转置,两端的面各只有一项),再乘 c_L,c_R, ± κ_f,最后经转置的重构权重累加到模板里每个未知量上。原始UUf−1​, …, Uf+2​qL​, qR​, UL​, UR​取值 + 重构Hf​ = Hc​ + Hv​面通量Rf​ += Hf​ (f ≥ 1)Rf+1​ −= Hf​ (f ≤ N−2)σj​H(qL​, qR​)分发切线U,D种子qL​,qR​,UL​,UR​同样的重构权重Hf​cL​qL​+ cR​qR​+ κf​ (UL​−UR​) + …Rf​+=Hf​Rf+1​−=Hf​σl​, σr​cL​, cR​, κf​同序伴随U+= …,D+= …转置的权重qL​= cL​Hf​,qR​= cR​Hf​UL​= κf​Hf​,UR​= −κf​Hf​Hf​=Rf​−Rf+1​取值(分发的转置)R种子 ψ 或 w+=cL​, cR​, κf​逆序三者共用网格、重构权重和在原始迹 qL​、qR​ 处求得的 cL​ = qL​/2 + 1、cR​ = qR​/2 − 1,以及 κf​ = ν/h;每个面两侧都是节点。
图 102 · 同一个面循环的三种用法。原始(蓝):重构面上的迹,算通量,分发到面两侧节点的对偶控制体(边界行是约束行,不参与分发)。切线(绿):按同样的顺序传播带点的量,用同样的重构权重和在原始迹处求得的 cL,cR,κfc_L,c_R,\kappa_f。伴随(红):从右向左,先从残差的种子取 Hˉf=Rˉf−Rˉf+1\bar H_f=\bar R_f-\bar R_{f+1}(分发的转置,两端的面各只有一项),再乘 cL,cR,±κfc_L,c_R,\pm\kappa_f,最后经转置的重构权重累加到模板里每个未知量上。
Figure 102 · The same face loop used three ways. Primal (blue): reconstruct the traces on the face, evaluate the flux, scatter it to the dual volumes of the two nodes on either side of the face (the boundary rows are constraint rows and take no part in the scatter). Tangent (green): propagate the dotted quantities in the same order, with the same reconstruction weights and the c_L,c_R,κ_f taken at the primal traces. Adjoint (red): from right to left, first gather H-bar_f=R-bar_f-R-bar_(f+1) from the residual seed (the transposed scatter; the two end faces have one term each), then multiply by c_L,c_R, ± κ_f, and finally accumulate through the transposed reconstruction weights into every unknown of the stencil.PrimalUUf−1​, …, Uf+2​qL​, qR​, UL​, UR​gather + reconstructHf​ = Hc​ + Hv​face fluxRf​ += Hf​ (f ≥ 1)Rf+1​ −= Hf​ (f ≤ N−2)σj​H(qL​, qR​)scatterTangentU,DseedsqL​,qR​,UL​,UR​the same weightsHf​cL​qL​+ cR​qR​+ κf​ (UL​−UR​) + …Rf​+=Hf​Rf+1​−=Hf​σl​, σr​cL​, cR​, κf​same orderAdjointU+= …,D+= …transposed weightsqL​= cL​Hf​,qR​= cR​Hf​UL​= κf​Hf​,UR​= −κf​Hf​Hf​=Rf​−Rf+1​gather (transposed scatter)Rseed ψ or w+=cL​, cR​, κf​reverse orderAll three share the mesh and the reconstruction weights, and cL​ = qL​/2 + 1 and cR​ = qR​/2 − 1 are taken at the primal traces qL​, qR​,and κf​ = ν/h; every face has a node on each side.
Figure 102 · The same face loop used three ways. Primal (blue): reconstruct the traces on the face, evaluate the flux, scatter it to the dual volumes of the two nodes on either side of the face (the boundary rows are constraint rows and take no part in the scatter). Tangent (green): propagate the dotted quantities in the same order, with the same reconstruction weights and the cL,cR,κfc_L,c_R,\kappa_f taken at the primal traces. Adjoint (red): from right to left, first gather Hˉf=Rˉf−Rˉf+1\bar H_f=\bar R_f-\bar R_{f+1} from the residual seed (the transposed scatter; the two end faces have one term each), then multiply by cL,cR,±κfc_L,c_R,\pm\kappa_f, and finally accumulate through the transposed reconstruction weights into every unknown of the stencil.

下面的播放器用当前控件,把这条链一步一步走一遍:每一步显示那一刻的数组。

The player below walks the chain step by step with the current controls, showing the arrays of each moment.

验证了什么,怎样验证

What was verified, and how

每一种检查回答一个不同的问题:点积检验问反向代码是不是前向代码的转置;“切线 = 伴随”问的是两个求解是否一致;复数步长和差分问导数是不是这个程序的导数;Python 数据问另一份独立实现是否给出同样的数;连续公式问连续推导本身;收敛阶问离散是否逼近连续。下表的数是本页在构建时运行各项检查所得的最大值,范围见各行所列的网格与种子(除非另注,取默认设计);各节打印的是它们自己的网格上的值,可能更小;“见”一栏给出解释该检查的小节;Python 审计(audit/audit_f.py 与 audit/ 中其他脚本)独立地复现了它们。点积检验的标准是 10−1410^{-14}:随机状态上最坏的相对差在 10−1510^{-15} 量级,10−1610^{-16} 低于舍入误差。

Each check answers a different question: the dot test asks whether the reverse code is the transpose of the tangent code; tangent = adjoint asks whether the two solves agree; complex step and finite differences ask whether the derivative is the derivative of this program; the Python data ask whether an independent implementation gives the same numbers; the continuous formula checks the continuous derivation itself; the orders ask whether the discretisation approaches the continuum. The numbers in the table are the largest values found by the checks that this page runs at build time, over the meshes and seeds named in each row (default design unless noted); the sections print the values for their own meshes, which can be smaller, and “See” names the section that explains the check; the Python audit (audit/audit_f.py and the other scripts in audit/) reproduces them independently. The dot test is held to 10−1410^{-14}: the worst relative difference over random states is of order 10−1510^{-15}, and 10−1610^{-16} is below rounding.

检查Check最大偏差Largest discrepancy见See
点积检验:前向代码与反向代码(随机状态与种子,N=8,16,33N=8,16,33,相对)dot test of the tangent and reverse code (random states and seeds, N=8,16,33N=8,16,33, relative)2.1e−15第 9 节Section 9
模型的代码与独立的 Python 参考实现(随机状态与种子:残差、前向与反向代码、Jacobian;相对,分母取 max⁡(1,∣y∣)\max(1,|y|),yy 为参考值)the model code against the independent Python reference (random states and seeds: residual, tangent and reverse code, Jacobians; relative, denominator max⁡(1,∣y∣)\max(1,|y|) with yy the reference value)4.8e−15第 8 节Section 8
切线梯度与伴随梯度之差(三种重构,N≤128N\le128)tangent gradient minus adjoint gradient (3 reconstructions, N≤128N\le128)5.9e−15第 11 节Section 11
贯穿整个求解的复数步长与伴随之差(N=8,16N=8,16)complex step through the solve minus adjoint (N=8,16N=8,16)1.2e−15第 14 节Section 14
扰动解的复残差 Im⁡R/τ\operatorname{Im}R/\taucomplex residual of the perturbed state, Im⁡R/τ\operatorname{Im}R/\tau1.1e−15第 14 节Section 14
GS 的 mm 步转置(相对)mm-step transposition of GS (relative)2.7e−15第 17 节Section 17
两个分块算法(内部块与第 0、NN 行)与完整求解之差(N=16N=16)the two blocked algorithms (interior block, rows 0 and NN) against the full solves (N=16N=16)8.3e−16第 17 节Section 17
中心差分(τ=10−5\tau=10^{-5},完整重算,N=8N=8)与伴随之差central differences (τ=10−5\tau=10^{-5}, full re-solves, N=8N=8) minus adjoint6.0e−9第 13 节Section 13
与 Python 数据中的梯度之差(三种重构,N=32,…,4096N=32,\dots,4096)difference from the gradients of the Python data (3 reconstructions, N=32,…,4096N=32,\dots,4096)8.9e−13第 15 节Section 15
乘子 ψ0\psi_0、ψN\psi_N 与 Python 数据之差(三种重构,N=32,…,4096N=32,\dots,4096)multipliers ψ0\psi_0, ψN\psi_N against the Python data (3 reconstructions, N=32,…,4096N=32,\dots,4096)3.8e−13第 16 节Section 16
ψ−λ\psi-\lambda 的 L1 范数与 Python 数据之差(相对)L1 norm of ψ−λ\psi-\lambda against the Python data (relative)4.2e−8第 16 节Section 16
默认设计的 Newton 解、伴随、梯度与 Python 参考实现之差(N=8,…,64N=8,\dots,64,三种重构,相对)Newton solutions, adjoints and gradients at the defaults against the Python reference (N=8,…,64N=8,\dots,64, 3 reconstructions, relative)1.1e−13第 11 节Section 11
连续梯度公式与精确梯度之差continuous gradient formula minus exact gradient1.0e−13附录 AAppendix A

收敛阶(Python 数据中最细的两层):无限制器线性的状态 L1 误差阶 2.00,梯度分量 dJ/da\mathrm dJ/\mathrm da 的误差阶 1.94(N=8192N=8192 到 16384);一阶格式为 1.00 与 1.00(N=8192N=8192 到 16384)。无限制器线性的梯度误差在模型的网格上变号(aa、ν\nu 分量不止一次),最后一次分别在 N=512N=512 与 1024(aa)、128 与 256(φ\varphi)、1024 与 2048(ν\nu)之间,这些点附近的观测阶不规则(第 16 节)。伴随本身:ψ−λ\psi-\lambda 的 L1 误差阶,无限制器线性 1.97(模型,N=4096N=4096),1.99(Python,N=16384N=16384;见第 15、16 节)。

Orders of convergence (between the two finest levels of the Python data): for unlimited linear reconstruction the state L1 error converges at 2.00 and the error of the gradient component dJ/da\mathrm dJ/\mathrm da at 1.94 (N=8192N=8192 to 16384); for the first-order scheme at 1.00 and 1.00 (N=8192N=8192 to 16384). The gradient errors of unlimited linear reconstruction change sign on the meshes of the model (more than once for aa and ν\nu), for the last time between N=512N=512 and 1024 (aa), between 128 and 256 (φ\varphi) and between 1024 and 2048 (ν\nu), and the observed orders are erratic around these meshes (Section 16). The adjoint itself: the L1 error of ψ−λ\psi-\lambda converges at 1.97 for unlimited linear (model, N=4096N=4096) and 1.99 (Python, N=16384N=16384; see Sections 15 and 16).

图 103 · 验证的阶梯(对数轴)。检验导数代码的各项(点积、独立参考、切线 = 伴随、复数步长、GS 转置、分块算法,绿色)都在舍入误差量级,最大 5.9 × 10^(-15)。与参考解的比较(紫色:Python 数据的梯度 9 × 10^(-13)、乘子 4 × 10^(-13) 和 ψ-λ 的 L1 范数 4 × 10^(-8),由本页 201 点 Chebyshev λ 与 solve_bvp 的差别决定;连续公式 1 × 10^(-13))都比导数检验的最大值大。中心差分(橙黄色)的 6 × 10^(-9) 是截断误差 (τ^2)/6|∂^3J_h/∂ D_k^3|:它来自光滑限制器的 φ 分量(∂^3J_h/∂ φ^3=361,(τ^2)/6|∂^3J_h|=6 × 10^(-9)),远大于舍入误差 ε_mach/τ ≈ 2 × 10^(-11)。在 N=64 到 512 的光滑限制器上,ν 轴需要 τ=10^(-6) 才能把差分误差压到 10^(-8) 以下。10-17​10-15​10-13​10-11​10-9​10-7​10-5​点积检验:前向与反向代码2.1e−15模型代码与 Python 参考实现4.8e−15切线梯度与伴随梯度之差5.9e−15贯穿整个求解的复数步长与伴随之差1.2e−15扰动解的复残差 Im R/τ1.1e−15GS 的 m 步转置(相对)2.7e−15分块算法与完整求解之差8.3e−16中心差分与伴随之差6.0e−9与 Python 数据中的梯度之差(N = 32 … 4096)8.9e−13乘子 ψ0​、ψN​ 与 Python 数据之差3.8e−13ψ − λ 的 L1 范数与 Python 数据之差(相对)4.2e−8默认设计与 Python 参考实现之差1.1e−13连续梯度公式与精确梯度之差1.0e−13导数代码的检验中心差分与参考解比较
图 103 · 验证的阶梯(对数轴)。检验导数代码的各项(点积、独立参考、切线 = 伴随、复数步长、GS 转置、分块算法,绿色)都在舍入误差量级,最大 5.9×10−155.9\times10^{-15}。与参考解的比较(紫色:Python 数据的梯度 9×10−139\times10^{-13}、乘子 4×10−134\times10^{-13} 和 ψ−λ\psi-\lambda 的 L1 范数 4×10−84\times10^{-8},由本页 201 点 Chebyshev λ\lambda 与 solve_bvp 的差别决定;连续公式 1×10−131\times10^{-13})都比导数检验的最大值大。中心差分(橙黄色)的 6×10−96\times10^{-9} 是截断误差 τ26∣∂3Jh/∂Dk3∣\tfrac{\tau^2}{6}|\partial^3J_h/\partial D_k^3|:它来自光滑限制器的 φ\varphi 分量(∂3Jh/∂φ3=361\partial^3J_h/\partial \varphi^3=361,τ26∣∂3Jh∣=6×10−9\tfrac{\tau^2}{6}|\partial^3J_h|=6\times10^{-9}),远大于舍入误差 ϵmach/τ≈2×10−11\epsilon_{\rm mach}/\tau\approx2\times10^{-11}。在 N=64N=64 到 512 的光滑限制器上,ν\nu 轴需要 τ=10−6\tau=10^{-6} 才能把差分误差压到 10−810^{-8} 以下。
Figure 103 · The verification ladder (logarithmic axis). The checks of the derivative code (dot test, independent reference, tangent = adjoint, complex step, GS transposition, blocked algorithms; green) sit at the level of rounding, at most 5.9 × 10^(-15); the comparisons with reference solutions (violet: the gradients of the Python data, 9 × 10^(-13), the multipliers, 4 × 10^(-13), and the L1 norm of ψ-λ, 4 × 10^(-8), set by the 201-point Chebyshev λ of the page against solve_bvp; the continuous formula, 1 × 10^(-13)) are larger than the largest derivative check; the 6 × 10^(-9) of central differences (amber) is the truncation error (τ^2)/6|∂^3J_h/∂ D_k^3| of the φ component of the smooth limiter (∂^3J_h/∂ φ^3=361, (τ^2)/6|∂^3J_h|=6 × 10^(-9)), far above the rounding error ε_mach/τ ≈ 2 × 10^(-11). For the smooth limiter at N=64 to 512 the ν axis needs τ=10^(-6) to bring the difference error below 10^(-8).10-17​10-15​10-13​10-11​10-9​10-7​10-5​dot test of tangent and reverse code2.1e−15model code against the Python reference4.8e−15tangent minus adjoint gradient5.9e−15complex step through the solve minus adjoint1.2e−15complex residual of the perturbed state, Im R/τ1.1e−15m-step transposition of GS (relative)2.7e−15blocked algorithms against full solves8.3e−16central differences minus adjoint6.0e−9gradients of the Python data (N = 32 … 4096)8.9e−13multipliers ψ0​, ψN​ against the Python data3.8e−13L1 norm of ψ − λ against the Python data (relative)4.2e−8defaults against the Python reference1.1e−13continuous gradient formula minus exact gradient1.0e−13checks of the derivative codecentral differencescomparisons with reference solutions
Figure 103 · The verification ladder (logarithmic axis). The checks of the derivative code (dot test, independent reference, tangent = adjoint, complex step, GS transposition, blocked algorithms; green) sit at the level of rounding, at most 5.9×10−155.9\times10^{-15}; the comparisons with reference solutions (violet: the gradients of the Python data, 9×10−139\times10^{-13}, the multipliers, 4×10−134\times10^{-13}, and the L1 norm of ψ−λ\psi-\lambda, 4×10−84\times10^{-8}, set by the 201-point Chebyshev λ\lambda of the page against solve_bvp; the continuous formula, 1×10−131\times10^{-13}) are larger than the largest derivative check; the 6×10−96\times10^{-9} of central differences (amber) is the truncation error τ26∣∂3Jh/∂Dk3∣\tfrac{\tau^2}{6}|\partial^3J_h/\partial D_k^3| of the φ\varphi component of the smooth limiter (∂3Jh/∂φ3=361\partial^3J_h/\partial \varphi^3=361, τ26∣∂3Jh∣=6×10−9\tfrac{\tau^2}{6}|\partial^3J_h|=6\times10^{-9}), far above the rounding error ϵmach/τ≈2×10−11\epsilon_{\rm mach}/\tau\approx2\times10^{-11}. For the smooth limiter at N=64N=64 to 512 the ν\nu axis needs τ=10−6\tau=10^{-6} to bring the difference error below 10−810^{-8}.

总览面板对当前控件把这些检查全部重做:原始解、切线与伴随梯度、对偶、点积检验、复数步长、中心差分、精确梯度、连续公式和两个乘子,放在一张表里。

The dashboard redoes all of these checks for the current controls: the primal solution, the tangent and adjoint gradients, the duality, the dot test, complex step, central differences, the exact gradient, the continuous formula and the two multipliers, in one table.

离散梯度是什么,不是什么

What the discrete gradient is, and what it is not

RDTψR_D^T\psi 是离散目标 Jh(D)J_h(D)(即这个网格上这段程序的目标)的梯度,精确到舍入误差(上表)。它不是连续目标 JJ 的梯度,只有加密网格才能逼近后者(第 15 节、第 16 节)。默认设计、N=8N=8 时,离散梯度是 (−0.1781, 0.4199, 0.0039)(−0.1781,\ 0.4199,\ 0.0039),连续梯度(闭式)是 (−0.1440, 0.0852, 0)(−0.1440,\ 0.0852,\ 0)。误差有三个来源(第 16 节):出口乘子 ψN\psi_N 在粗网格上相对误差很大,入口附近的节点(ψ1\psi_1 偏离 λ(x1)\lambda(x_1))补上了没有源项行的第一个半控制体,目标的梯形公式带来 h212∂Dkux∗(0)\tfrac{h^2}{12}\partial_{D_k}u^*_x(0);φ\varphi 分量最坏,差 0.335。用 RDTψR_D^T\psi 的优化器优化的是这个网格上的 JhJ_h;结果是否接近连续最优,取决于离散化在重要的地方是否足够准——这里是入口层附近的节点和边界面。

RDTψR_D^T\psi is the gradient of the discrete objective Jh(D)J_h(D), the objective of this program on this mesh, exact up to rounding (table above). It is not the gradient of the continuous objective JJ; that one is approached only as the mesh is refined (Section 15, Section 16). At the defaults with N=8N=8 the discrete gradient is (−0.1781, 0.4199, 0.0039)(−0.1781,\ 0.4199,\ 0.0039) and the continuous one (closed form) (−0.1440, 0.0852, 0)(−0.1440,\ 0.0852,\ 0). The error has three sources (Section 16): the outlet multiplier ψN\psi_N, whose relative error is large on coarse meshes; the nodes next to the inlet (ψ1\psi_1 is off from λ(x1)\lambda(x_1)), which make up for the first half volume that has no source row; and the trapezoid rule of the objective, h212∂Dkux∗(0)\tfrac{h^2}{12}\partial_{D_k}u^*_x(0). The φ\varphi component is the worst, off by 0.335. An optimiser that uses RDTψR_D^T\psi optimises JhJ_h on that mesh; whether the result is close to the continuous optimum depends on whether the discretisation is accurate where it matters, here the nodes near the inlet layer and the boundary faces.

格点格式与格心格式

The node-centred scheme against the cell-centred scheme

两个页面解同一个问题:同一个方程、构造解、设计、目标、Rusanov 通量和重构。差别在未知量放在哪里,以及由此带来的边界处理。下表左栏是格心页,右栏是本页;最后一栏是这一项差别在数字上的表现(格心页的数字来自它自己的独立审计)。结论不是“格点格式处处更好”:无限制器线性在 Python 数据的所有网格上三个分量的梯度误差都更小,但一阶格式的 aa、φ\varphi 分量并不更好,N=8N=8 时 φ\varphi 分量反而更差。格心页的附录 B 在 N=8N=8 到 64 上并排比较了两种格式(两张图、一张表和一个面板),这里不重复。

The two pages solve the same problem: the same equation, manufactured solution, design, objective, Rusanov flux and reconstructions. What differs is where the unknowns live and, with it, the treatment of the boundary. In the table the left column is the cell-centred page, the right column this page; the last column is what the difference does to the numbers (the cell page's numbers come from its own independent audit). The conclusion is not “the node scheme is better everywhere”: for unlimited linear reconstruction the gradient errors of all three components are smaller on every mesh of the Python data, but for the first-order scheme the aa and φ\varphi components are not better, and at N=8N=8 the φ\varphi component is worse. Appendix B of the cell-centred page compares the two schemes side by side at N=8N=8 to 64 (two figures, a table and a lab); this is not repeated here.

格心页Cell-centred page本页(节点)This page (nodes)数字上的表现What it does to the numbers
未知量与误差的参照Unknowns and the reference of the errorsNN 个单元平均;误差对精确单元平均NN cell averages; errors against the exact cell averagesN+1N+1 个节点点值;误差对精确节点值N+1N+1 point values; errors against the exact nodal valuesN=8N=8、无限制器线性的状态 L1 误差:5.23e−2(格心)、1.33e−2(节点)state L1 error at N=8N=8, unlimited linear: 5.23e−2 (cells), 1.33e−2 (nodes)
边界Boundary边界面距未知量 h/2h/2,读 uin,uoutu_{\rm in},u_{\rm out};入口值伴随 uˉin=−ψ0 (cL(0)+2ν/h)\bar u_{\rm in}=-\psi_0\,(c_L(0)+2\nu/h)boundary faces at h/2h/2 from the unknown read uin,uoutu_{\rm in},u_{\rm out}; the adjoint of the inlet value is uˉin=−ψ0 (cL(0)+2ν/h)\bar u_{\rm in}=-\psi_0\,(c_L(0)+2\nu/h)第 0 行和第 NN 行是约束行;梯度的边界项就是 −ψ0 ∂uin−ψN ∂uout-\psi_0\,\partial u_{\rm in}-\psi_N\,\partial u_{\rm out}rows 0 and NN are constraints; the boundary term of the gradient is −ψ0 ∂uin−ψN ∂uout-\psi_0\,\partial u_{\rm in}-\psi_N\,\partial u_{\rm out}N=8N=8:uˉin\bar u_{\rm in} 离 −νλx(0)-\nu\lambda_x(0) 4.8%(格心);ψ0\psi_0 离 νλx(0)\nu\lambda_x(0) 1.4%(节点)N=8N=8: uˉin\bar u_{\rm in} is 4.8% from −νλx(0)-\nu\lambda_x(0) (cells); ψ0\psi_0 is 1.4% from νλx(0)\nu\lambda_x(0) (nodes)
伴随的斜率The slope of the adjointψ0/(h/2)→λx(0)\psi_0/(h/2)\to\lambda_x(0)ψ0/(h/2)→λx(0)\psi_0/(h/2)\to\lambda_x(0)ψ1/h→λx(0)\psi_1/h\to\lambda_x(0)ψ1/h→λx(0)\psi_1/h\to\lambda_x(0)进入 10% 以内要 N=1024N=1024(格心)、N=512N=512(节点)within 10% needs N=1024N=1024 (cells), N=512N=512 (nodes)
边界的重构Reconstruction at the boundary两个端单元不重构(σ0=σN−1=0\sigma_0=\sigma_{N-1}=0):迹只有一阶精度,带额外黏性 h/2h/2the two end cells are not reconstructed (σ0=σN−1=0\sigma_0=\sigma_{N-1}=0): first-order traces, added viscosity h/2h/2边界节点取单侧斜率:迹二阶精度,边界面的跳跃比一阶格式小一个 O(h)O(h) 因子(只在第 1 行与第 N−1N-1 行上有约 h/4h/4 的额外黏性,第 3 节)one-sided slopes at the boundary nodes: second-order traces, the jump across a boundary face is O(h)O(h) times the first-order one (an added viscosity of about h/4h/4 on rows 1 and N−1N-1 only, Section 3)N=8N=8 的 aa 分量梯度误差:0.343(格心)、0.034(节点);格点格式去掉边界斜率后 0.671aa-gradient error at N=8N=8: 0.343 (cells), 0.034 (nodes); the node scheme without its boundary slopes: 0.671
一阶格式First-order scheme内部行(除两个端行)是黏性 ν+h\nu+h 的中心格式the interior rows (except the two end rows) are the central scheme with viscosity ν+h\nu+h所有内部行如此;ψ0,ψN\psi_0,\psi_N 由第 0、NN 行读出all interior rows are; ψ0,ψN\psi_0,\psi_N are read off rows 0 and NNN=8N=8 时层宽是 ν/uin\nu/u_{\rm in} 的 13.5 倍(两页相同)at N=8N=8 the layer is 13.5 times wider than ν/uin\nu/u_{\rm in} (on both pages)
默认设计、N=8N=8 的梯度误差(a,φ,νa,\varphi,\nu)Gradient errors at the defaults, N=8N=8 (a,φ,νa,\varphi,\nu)0.343、0.146、0.3100.343, 0.146, 0.3100.034、0.335、0.00390.034, 0.335, 0.0039无限制器线性:aa、ν\nu 节点好得多,φ\varphi 格心更好unlimited linear: much better for aa and ν\nu on nodes, better for φ\varphi on cells
加密时的梯度误差(Python 数据)Gradient errors under refinement (Python data)————无限制器线性:三个分量在每个网格上都更好(aa 的误差之比 3.7e−4 到 5.0e−2);一阶:aa、φ\varphi 不更好(之比 1.01 到 1.42、1.02 到 5.13),只有 ν\nu 更好unlimited linear: better in all three components on every mesh (error ratio for aa from 3.7e−4 to 5.0e−2); first order: not better for aa and φ\varphi (ratios 1.01 to 1.42 and 1.02 to 5.13), only for ν\nu
GS 迭代GS iterationsN=128N=128,无限制器线性,切线/伴随:642 / 704,ρ=0.9481\rho=0.9481N=128N=128, unlimited linear, tangent / adjoint: 642 / 704, ρ=0.9481\rho=0.9481660 / 702,ρ=0.9478\rho=0.9478660 / 702, ρ=0.9478\rho=0.9478几乎相同almost the same
错误的边界处理The boundary slip边界面距离取 hh:ψ0/(h/2)→2λx(0)\psi_0/(h/2)\to2\lambda_x(0),uˉin\bar u_{\rm in} 看不出boundary-face distance hh: ψ0/(h/2)→2λx(0)\psi_0/(h/2)\to2\lambda_x(0), uˉin\bar u_{\rm in} does not show it边界面距离取 h/2h/2:ψ1/h→λx(0)/2\psi_1/h\to\lambda_x(0)/2,乘子 ψ0→νλx(0)\psi_0\to\nu\lambda_x(0) 看不出boundary-face distance h/2h/2: ψ1/h→λx(0)/2\psi_1/h\to\lambda_x(0)/2, the multiplier ψ0→νλx(0)\psi_0\to\nu\lambda_x(0) does not show it两个页面里都只有一阶收敛,导数检验全部通过first order only on both pages, every derivative check passes

本页的局限

The limits of this page

  • 固定的正黏性(控件中 0.001≤ν≤10.001\le\nu\le1),没有激波;ν→0\nu\to0 与 h→0h\to0 的极限顺序没有处理(第 16 节只比较几个固定的 ν\nu,渐近分析也只是形式推导)。A fixed positive viscosity (0.001≤ν≤10.001\le\nu\le1 in the controls) and no shocks; the order of the limits ν→0\nu\to0, h→0h\to0 is not treated (Section 16 compares several fixed values of ν\nu and gives formal asymptotics only).
  • 一个光滑的构造解(周期的 u∗u^*,所以 uin=uoutu_{\rm in}=u_{\rm out})、一个目标、三个设计分量;Rusanov 速度固定为 α=2\alpha=2,光滑限制器取 ϵ=0.01\epsilon=0.01。uin=uoutu_{\rm in}=u_{\rm out} 使 aa、φ\varphi 分量只通过两个乘子之和看到它们;无限制器线性时两个误差几乎等大反号,一阶格式时同号相加(第 16 节);一般的设计没有这种结构。One smooth manufactured solution (periodic u∗u^*, so uin=uoutu_{\rm in}=u_{\rm out}), one objective and three design components; the Rusanov speed is fixed at α=2\alpha=2 and the smooth limiter uses ϵ=0.01\epsilon=0.01. That uin=uoutu_{\rm in}=u_{\rm out} makes the aa and φ\varphi components see the two multipliers only through their sum; for unlimited linear reconstruction their errors are nearly equal and opposite, for the first-order scheme they have the same sign and add (Section 16); a general design would not have this structure.
  • 本页不给出非线性问题或格式的存在性与唯一性定理;已证明的收敛估计只有第 4 节的一阶稳定性界(用面误差控制误差,要求解落在 Newton 法的范围 0.1<U<1.90.1<U<1.9 内);其余每个观测到的收敛阶都只是本问题上的数值证据(第 4–7 节与附录 A 的 A.4 中的证明针对那里写明的线性方程组、单步估计、该稳定性界和恒等式);第 16 节的渐近分析是形式推导,乘子与伴随的关系是观测,不是定理。No existence or uniqueness theorem for the nonlinear problem or the scheme is given, and the only convergence estimate that is proved is the first-order stability bound of Section 4 (an error bound by the face errors, valid for solutions inside Newton's box 0.1<U<1.90.1<U<1.9); every other observed order is numerical evidence for this one problem (the proofs of Sections 4–7 and of A.4 in Appendix A concern the linear systems, one-step estimates, that bound and the identities named there); the asymptotics of Section 16 are formal, and the relation of the multipliers to the continuous adjoint is an observation, not a theorem.
  • 第 17 节的迭代是为了讲清结构,没有调优;一维里带状 LU 更便宜。The iterations of Section 17 are there to show their structure and are not tuned; in one dimension the band LU is cheaper.

接下来读什么

Where to go next

  • 附录 A:用变分推出连续伴随与梯度公式,以及它的边界项。Appendix A: the continuous adjoint and the gradient formula with its boundary term, derived with variations.
  • 附录 B:一个 Dirichlet–Neumann 格点格式的基准算例。Appendix B: a Dirichlet–Neumann nodal benchmark.
  • 附录 C:怎样复现本页的数字和 Python 数据。Appendix C: how to reproduce the numbers of this page and the Python data.

要记住的

What to remember

  • 切线与伴随用自动微分的记号:切线是 x˙\dot x、按原顺序;伴随是 xˉ\bar x、按逆序累加 +=\mathrel{\text{+=}};二者由对偶 RˉTR˙=𝐔ˉT𝐔˙+DˉTD˙\bar R^T\dot R=\bar{\mathbf U}^T\dot{\mathbf U}+\bar D^T\dot D 连在一起。The tangent and the adjoint use the notation of automatic differentiation: the tangent is x˙\dot x in the original order, the adjoint xˉ\bar x accumulated with +=\mathrel{\text{+=}} in reverse order; the duality RˉTR˙=𝐔ˉT𝐔˙+DˉTD˙\bar R^T\dot R=\bar{\mathbf U}^T\dot{\mathbf U}+\bar D^T\dot D ties them together.
  • 核心就是一个面:取值、重构、通量、分发;切线与伴随复用同样的局部导数 cL,cR,κfc_L,c_R,\kappa_f 和重构权重。边界行是约束行,不进入分发。One face is everything: gather, reconstruct, flux, scatter; the tangent and the adjoint reuse the same local derivatives cL,cR,κfc_L,c_R,\kappa_f and reconstruction weights. The boundary rows are constraints and take no part in the scatter.
  • 伴随梯度是离散目标的导数,精确到舍入误差:用点积检验、复数步长和差分验证它;用加密和连续伴随检验它离连续梯度有多远。The adjoint gradient is the derivative of the discrete objective, exact up to rounding: verify it with the dot test, complex step and finite differences; check how far it is from the continuous gradient with refinement and the continuous adjoint.
  • 积分形式的残差使人预期内部节点上 ψj≈λ(xj)\psi_j\approx\lambda(x_j)(同号、无因子 hh),两个约束行的乘子趋于连续伴随的边界通量;本页的测量:ψj→λ(xj)\psi_j\to\lambda(x_j)、ψ0→νλx(0)\psi_0\to\nu\lambda_x(0)、ψN→−νλx(1)\psi_N\to-\nu\lambda_x(1),同阶(无限制器线性二阶,一阶格式一阶)。默认设计下 N=8N=8 时 ψ0\psi_0 就只差 1.4%,尽管伴随的层(宽 ν/uin\nu/u_{\rm in})没有被分辨;ψN\psi_N 的相对误差则很大(−νλx(1)-\nu\lambda_x(1) 很小),别的设计在粗网格上也可能差得多(第 16 节)。分辨层需要 h<ν/uinh<\nu/u_{\rm in}。An integrated residual leads one to expect ψj≈λ(xj)\psi_j\approx\lambda(x_j) at the interior nodes (the same sign, no factor hh) and the multipliers of the two constraint rows to approach the boundary fluxes of the continuous adjoint; measured here: ψj→λ(xj)\psi_j\to\lambda(x_j), ψ0→νλx(0)\psi_0\to\nu\lambda_x(0) and ψN→−νλx(1)\psi_N\to-\nu\lambda_x(1) at the same order (second for unlimited linear, first for the first-order scheme). At the default design and N=8N=8, ψ0\psi_0 is already within 1.4% of νλx(0)\nu\lambda_x(0) although the adjoint's layer (width ν/uin\nu/u_{\rm in}) is not resolved; the relative error of ψN\psi_N is large (−νλx(1)-\nu\lambda_x(1) is small), and other designs can be much worse on a coarse mesh (Section 16). Resolving the layer needs h<ν/uinh<\nu/u_{\rm in}.
  • 一阶格式等于黏性为 ν+h\nu+h 的中心格式(所有内部行)。一个把距离写错的边界面能让所有导数检验通过,却使二阶降为一阶:乘子比值看不出来,斜率 ψ1/h→λx(0)/2\psi_1/h\to\lambda_x(0)/2 才看得出来。The first-order scheme is the central scheme with viscosity ν+h\nu+h (in all interior rows). A boundary face with a wrong distance passes every derivative check and drops second order to first: the multiplier ratio does not show it, the slope ψ1/h→λx(0)/2\psi_1/h\to\lambda_x(0)/2 does.
  • 伴随迭代应当是切线迭代的转置:转置的 GS 反向扫描,截断导数在每一步都相等;GMRES 不是线性的,只有收敛后才满足对偶关系。The adjoint iteration should be the transpose of the tangent iteration: transposed GS sweeps backward and the truncated derivatives agree at every step; GMRES is not linear and satisfies the duality only at convergence.

附录 A:连续伴随

Appendix A: The continuous adjoint

本节实验:ν\nu 越小,连续伴随在 x=0x=0 处的斜率 λx(0)\lambda_x(0) 越陡。梯度公式里的边界项 ν[λxvk]01\nu\bigl[\lambda_x v_k\bigr]_0^1 会随 ν→0\nu\to0 消失吗?先猜,再用图 107 和本附录的 ν\nu 实验台验证。

Experiment: as ν\nu decreases, the slope λx(0)\lambda_x(0) of the continuous adjoint at x=0x=0 steepens. Does the boundary term ν[λxvk]01\nu\bigl[\lambda_x v_k\bigr]_0^1 of the gradient formula vanish as ν→0\nu\to0? Guess first, then check with Figure 107 and the ν\nu lab of this appendix.

正文各节对离散程序求导:前向用点 x˙\dot x,伴随用横线 xˉ\bar x。本附录换一个对象:直接对连续方程求伴随。这样得到的 λ(x)\lambda(x) 正是离散伴随 ψ\psi 在网格加密时应当逼近的函数:内部节点上 ψj≈λ(xj)\psi_j\approx\lambda(x_j),两个约束行的乘子 ψ0\psi_0、ψN\psi_N 逼近边界通量 νλx(0)\nu\lambda_x(0) 与 −νλx(1)-\nu\lambda_x(1)(第 16 节;A.7 先给出本页网格上的测量);推导也说明它的边界条件从哪里来。这里用变分记号:δu\delta u、δs\delta s、δJ\delta J 是连续函数的变分;δ\delta 只出现在本附录(以及明确说“连续”的句子里)。

The main sections differentiate the discrete code: the tangent with dots x˙\dot x, the adjoint with bars xˉ\bar x. This appendix takes a different object, the continuous equation itself, and derives its adjoint. The result is the function λ(x)\lambda(x) that the discrete adjoint ψ\psi should approach under mesh refinement: ψj≈λ(xj)\psi_j\approx\lambda(x_j) at the interior nodes, and the multipliers ψ0\psi_0, ψN\psi_N of the two constraint rows approach the boundary fluxes νλx(0)\nu\lambda_x(0) and −νλx(1)-\nu\lambda_x(1) (Section 16; A.7 gives the measurements on this page's mesh). The derivation also shows where the boundary conditions of λ\lambda come from. The notation here is variational: δu\delta u, δs\delta s, δJ\delta J are variations of continuous functions; δ\delta appears only in this appendix (and in sentences that say continuous).

A.1 状态方程、目标与变分

A.1 The state equation, the objective and their variations

连续问题就是第 1 节的方程:总通量 q=12u2−νuxq=\tfrac12u^2-\nu u_x,

The continuous problem is the equation of Section 1: with the total flux q=12u2−νuxq=\tfrac12u^2-\nu u_x,

qx=s(x;D)在 (0,1) 上,u(0)=uin(D),u(1)=uout(D),J(u)=∫01(1+x) u dx.q_x=s(x;D)\quad\text{在 }(0,1)\text{ 上},\qquad u(0)=u_{\rm in}(D),\quad u(1)=u_{\rm out}(D),\qquad J(u)=\int_0^1(1+x)\,u\,\mathrm dx.
qx=s(x;D)on (0,1),u(0)=uin(D),u(1)=uout(D),J(u)=∫01(1+x) u dx.q_x=s(x;D)\quad\text{on }(0,1),\qquad u(0)=u_{\rm in}(D),\quad u(1)=u_{\rm out}(D),\qquad J(u)=\int_0^1(1+x)\,u\,\mathrm dx.

设计改变 δD\delta D 时,源项改变 δs\delta s,两端给定值改变 δuin\delta u_{\rm in}、δuout\delta u_{\rm out},状态随之改变 δu\delta u。把通量线性化:δq=u δu−ν δux−ux δν\delta q=u\,\delta u-\nu\,\delta u_x-u_x\,\delta\nu(最后一项只在 ν\nu 本身改变时出现,因为 ν\nu 写在通量里)。于是线性化的状态方程是

When the design changes by δD\delta D, the source changes by δs\delta s, the two prescribed end values by δuin\delta u_{\rm in}, δuout\delta u_{\rm out}, and the state follows with δu\delta u. Linearise the flux: δq=u δu−ν δux−ux δν\delta q=u\,\delta u-\nu\,\delta u_x-u_x\,\delta\nu (the last term appears only when ν\nu itself changes, because ν\nu sits inside the flux). The linearised state equation is therefore

(u δu−ν δux)x=δs+uxx δν,δu(0)=δuin,δu(1)=δuout.\bigl(u\,\delta u-\nu\,\delta u_x\bigr)_x=\delta s+u_{xx}\,\delta\nu,\qquad \delta u(0)=\delta u_{\rm in},\quad \delta u(1)=\delta u_{\rm out}.

每次只改变一个分量 DkD_k,除以 δDk\delta D_k,就得到连续切线解 vk=∂u/∂Dkv_k=\partial u/\partial D_k:对 aa、φ\varphi 有 (uvk−νvk,x)x=∂s/∂Dk(u v_k-\nu v_{k,x})_x=\partial s/\partial D_k,vk(0)=∂uin/∂Dkv_k(0)=\partial u_{\rm in}/\partial D_k,vk(1)=∂uout/∂Dkv_k(1)=\partial u_{\rm out}/\partial D_k;对 Dk=νD_k=\nu 有 (uvk−νvk,x)x=sν+uxx(uv_k-\nu v_{k,x})_x=s_\nu+u_{xx},两端 vk=0v_k=0。它是离散切线解 v=𝐔˙v=\dot{\mathbf U} 的连续对应物。

Moving one component DkD_k at a time and dividing by δDk\delta D_k gives the continuous tangent vk=∂u/∂Dkv_k=\partial u/\partial D_k: for aa and φ\varphi, (uvk−νvk,x)x=∂s/∂Dk(u v_k-\nu v_{k,x})_x=\partial s/\partial D_k with vk(0)=∂uin/∂Dkv_k(0)=\partial u_{\rm in}/\partial D_k and vk(1)=∂uout/∂Dkv_k(1)=\partial u_{\rm out}/\partial D_k; for Dk=νD_k=\nu, (uvk−νvk,x)x=sν+uxx(uv_k-\nu v_{k,x})_x=s_\nu+u_{xx} with vk=0v_k=0 at both ends. It is the continuous counterpart of the discrete tangent v=𝐔˙v=\dot{\mathbf U}.

A.2 拉格朗日函数与两次分部积分

A.2 The Lagrangian and two integrations by parts

把方程乘以一个待定的函数 λ(x)\lambda(x),加到目标上:

Multiply the equation by a function λ(x)\lambda(x), still to be chosen, and add it to the objective:

ℒ(u,D,λ)=J(u)+∫01λ [qx−s] dx.\mathcal L(u,D,\lambda)=J(u)+\int_0^1\lambda\,\bigl[q_x-s\bigr]\,\mathrm dx .

对状态方程的任何解,方括号内的量都为零,所以对任意 λ\lambda 都有 ℒ=J\mathcal L=J,变分也相同:δJ=δℒ\delta J=\delta\mathcal L。这正是正文 Jh+ψTRJ_h+\psi^TR 的连续版本,正负号约定一致(第 16 节比较 ψ\psi 与 λ\lambda 时无须变号)。对设计求变分:

On any solution of the state equation the bracket vanishes, so ℒ=J\mathcal L=J for every λ\lambda, and so do their variations: δJ=δℒ\delta J=\delta\mathcal L. This is the continuous version of the main text's Jh+ψTRJ_h+\psi^TR with the same sign convention (Section 16 compares ψ\psi with λ\lambda without a change of sign). Vary the design:

δℒ=∫01(1+x) δu dx+∫01λ [(u δu−ν δux)x−δs−uxx δν]dx.\delta\mathcal L=\int_0^1(1+x)\,\delta u\,\mathrm dx+\int_0^1\lambda\,\Bigl[\bigl(u\,\delta u-\nu\,\delta u_x\bigr)_x-\delta s-u_{xx}\,\delta\nu\Bigr]\mathrm dx .

中间一项含未知的 δu\delta u 的导数。我们要把导数从 δu\delta u 挪到 λ\lambda 上,一步一步来:(1)分部积分一次;(2)展开括号;(3)对 ν∫λx δux\nu\int\lambda_x\,\delta u_x 再分部积分一次:

The middle term contains derivatives of the unknown δu\delta u. Move them from δu\delta u onto λ\lambda, one step at a time: (1) integrate by parts once; (2) expand the bracket; (3) integrate ν∫λx δux\nu\int\lambda_x\,\delta u_x by parts again:

∫01λ (u δu−ν δux)x dx=[λ(u δu−ν δux)]01−∫01λx (u δu−ν δux) dx(1)=[λ(u δu−ν δux)]01−∫01uλx δu dx+ν∫01λx δux dx(2)=[λ(u δu−ν δux)]01+ν[λx δu]01−∫01(uλx+νλxx) δu dx(3)\begin{aligned}\int_0^1\lambda\,(u\,\delta u-\nu\,\delta u_x)_x\,\mathrm dx&=\bigl[\lambda(u\,\delta u-\nu\,\delta u_x)\bigr]_0^1-\int_0^1\lambda_x\,(u\,\delta u-\nu\,\delta u_x)\,\mathrm dx&&\text{(1)}\\&=\bigl[\lambda(u\,\delta u-\nu\,\delta u_x)\bigr]_0^1-\int_0^1u\lambda_x\,\delta u\,\mathrm dx+\nu\int_0^1\lambda_x\,\delta u_x\,\mathrm dx&&\text{(2)}\\&=\bigl[\lambda(u\,\delta u-\nu\,\delta u_x)\bigr]_0^1+\nu\bigl[\lambda_x\,\delta u\bigr]_0^1-\int_0^1\bigl(u\lambda_x+\nu\lambda_{xx}\bigr)\,\delta u\,\mathrm dx&&\text{(3)}\end{aligned}

代回 δℒ\delta\mathcal L,按“内部”和“两端”整理:

Put this back into δℒ\delta\mathcal L and sort it into the interior and the two ends:

δℒ=∫01[(1+x)−uλx−νλxx]δu dx+[λ(u δu−ν δux)]01+ν[λx δu]01−∫01λ (δs+uxx δν) dx.\delta\mathcal L=\int_0^1\Bigl[(1+x)-u\lambda_x-\nu\lambda_{xx}\Bigr]\delta u\,\mathrm dx+\bigl[\lambda(u\,\delta u-\nu\,\delta u_x)\bigr]_0^1+\nu\bigl[\lambda_x\,\delta u\bigr]_0^1-\int_0^1\lambda\,\bigl(\delta s+u_{xx}\,\delta\nu\bigr)\,\mathrm dx .

A.3 选 λ:伴随方程及其边界条件

A.3 Choosing λ: the adjoint equation and its boundary conditions

δu\delta u 只有解完切线问题才知道。我们选 λ\lambda,让所有含 δu\delta u 的项都消失,图 104 画出了这四项:

δu\delta u is known only after solving the tangent problem. Choose λ\lambda so that every term containing δu\delta u disappears; Figure 104 draws the four pieces:

  • 内部。被积函数为零:−uλx−νλxx=−(1+x)-u\lambda_x-\nu\lambda_{xx}=-(1+x)。右端项 −(1+x)-(1+x) 来自目标的权重。Interior. The integrand vanishes: −uλx−νλxx=−(1+x)-u\lambda_x-\nu\lambda_{xx}=-(1+x). The right side −(1+x)-(1+x) comes from the weight of the objective.
  • 两端的第一项 [λ(u δu−ν δux)]01\bigl[\lambda(u\,\delta u-\nu\,\delta u_x)\bigr]_0^1 含扰动状态在两端的斜率 δux(0)\delta u_x(0)、δux(1)\delta u_x(1)——它们是切线问题的输出,事先不知道。唯一的办法是让它们的系数为零:λ(0)=λ(1)=0\lambda(0)=\lambda(1)=0。这样 λu δu\lambda u\,\delta u 也一起消失。The first end term [λ(u δu−ν δux)]01\bigl[\lambda(u\,\delta u-\nu\,\delta u_x)\bigr]_0^1 contains the end slopes δux(0)\delta u_x(0), δux(1)\delta u_x(1) of the perturbed state: they are outputs of the tangent problem, unknown beforehand. The only way out is to make their coefficients zero: λ(0)=λ(1)=0\lambda(0)=\lambda(1)=0. Then λu δu\lambda u\,\delta u disappears as well.
  • 两端的第二项 ν[λx δu]01=νλx(1) δuout−νλx(0) δuin\nu\bigl[\lambda_x\,\delta u\bigr]_0^1=\nu\lambda_x(1)\,\delta u_{\rm out}-\nu\lambda_x(0)\,\delta u_{\rm in} 只含给定端值的变分,是已知的:它留下来,成为梯度的一部分。The second end term ν[λx δu]01=νλx(1) δuout−νλx(0) δuin\nu\bigl[\lambda_x\,\delta u\bigr]_0^1=\nu\lambda_x(1)\,\delta u_{\rm out}-\nu\lambda_x(0)\,\delta u_{\rm in} contains only variations of the prescribed end values, which are known: it stays and becomes part of the gradient.

二阶方程配两个条件,数目正好。若再对 λx\lambda_x 加条件,问题就超定;少一个,就留下一个算不出的项。结果是连续伴随问题与梯度公式:

A second-order equation with two conditions: exactly the right number. One more condition on λx\lambda_x would overdetermine the problem; one fewer would leave a term that cannot be evaluated. The result is the continuous adjoint problem and the gradient formula:

−uλx−νλxx=−(1+x),λ(0)=λ(1)=0,-u\lambda_x-\nu\lambda_{xx}=-(1+x),\qquad \lambda(0)=\lambda(1)=0,
dJdDk=−∫01λ ∂s∂Dk dx+ν(λx(1)∂uout∂Dk−λx(0)∂uin∂Dk)(Dk=a,φ),dJdν=−∫01λ (sν+uxx) dx.\frac{\mathrm dJ}{\mathrm dD_k}=-\int_0^1\lambda\,\frac{\partial s}{\partial D_k}\,\mathrm dx+\nu\Bigl(\lambda_x(1)\frac{\partial u_{\rm out}}{\partial D_k}-\lambda_x(0)\frac{\partial u_{\rm in}}{\partial D_k}\Bigr)\quad(D_k=a,\varphi),\qquad \frac{\mathrm dJ}{\mathrm d\nu}=-\int_0^1\lambda\,\bigl(s_\nu+u_{xx}\bigr)\,\mathrm dx .

ν\nu 分量没有边界项(端值不依赖 ν\nu),但多了物理通量本身的一项 −∫λuxx-\int\lambda u_{xx}。对构造解,源项 s=u∗ux∗−νuxx∗s=u^*u^*_x-\nu u^*_{xx} 给出 sν=−uxx∗s_\nu=-u^*_{xx},所以在 u=u∗u=u^* 上被积函数 sν+uxxs_\nu+u_{xx} 处处为零,dJ/dν=0\mathrm dJ/\mathrm d\nu=0,与 ∂J∗/∂ν=0\partial J^*/\partial\nu=0 一致。

The ν\nu component has no boundary term (the end values do not depend on ν\nu) but one more term from the physical flux itself, −∫λuxx-\int\lambda u_{xx}. For the manufactured solution the source s=u∗ux∗−νuxx∗s=u^*u^*_x-\nu u^*_{xx} gives sν=−uxx∗s_\nu=-u^*_{xx}, so the integrand sν+uxxs_\nu+u_{xx} vanishes identically at u=u∗u=u^* and dJ/dν=0\mathrm dJ/\mathrm d\nu=0, in agreement with ∂J∗/∂ν=0\partial J^*/\partial\nu=0.

常见错误:漏掉通量项,只算 −∫01λsν dx-\int_0^1\lambda s_\nu\,\mathrm dx。默认设计下这个数是 1.8769,而正确答案是 0:通量项 −∫01λuxx dx=−1.8769-\int_0^1\lambda u_{xx}\,\mathrm dx=−1.8769 恰好把它抵消(图 106 右)。离散的情形相同:第 12 节的 ν\nu 路径有一条直接穿过通量 HfH_f。

A common mistake: dropping the flux term and computing only −∫01λsν dx-\int_0^1\lambda s_\nu\,\mathrm dx. At the defaults that number is 1.8769, whereas the correct answer is 0: the flux term −∫01λuxx dx=−1.8769-\int_0^1\lambda u_{xx}\,\mathrm dx=−1.8769 cancels it exactly (Figure 106, right). The discrete case is the same: one of the ν\nu paths of Section 12 runs straight through the flux HfH_f.

图 104 · 两次分部积分之后的 L。三项(灰)由选择 λ 消去:内部靠伴随方程,两端的 λ(u u-ν u_x) 靠 λ(0)=λ(1)=0——因为 u_x 在两端未知。第四项(紫)只含给定端值的变分,留在梯度里。中间是本页默认设计下真实的 λ(x):两端为零,x=0 处斜率 λ_x(0)=−142.66。δℒ 在 [0,1] 上分部积分两次之后的四项本页的 λ(x)(默认设计),两端 λ = 0x = 0x = 1λx​(0) = −142.7(陡:边界层)λx​(1) = 2.20x = 0:[λ(u δu − ν δux​)]δux​(0) 未知 ⇒ λ(0) = 0这一项消失✕内部:∫[(1+x) − uλx​ − νλxx​] δu伴随方程 ⇒ 被积函数 = 0这一项消失✕x = 1:[λ(u δu − ν δux​)]δux​(1) 未知 ⇒ λ(1) = 0这一项消失✕ν[λx​ δu]0​1​ = ν λx​(1) δuout​ − ν λx​(0) δuin​δuin​、δuout​ 是给定数据的变分:这一项留在梯度里✓
图 104 · 两次分部积分之后的 δℒ\delta\mathcal L。三项(灰)由选择 λ\lambda 消去:内部靠伴随方程,两端的 λ(u δu−ν δux)\lambda(u\,\delta u-\nu\,\delta u_x) 靠 λ(0)=λ(1)=0\lambda(0)=\lambda(1)=0——因为 δux\delta u_x 在两端未知。第四项(紫)只含给定端值的变分,留在梯度里。中间是本页默认设计下真实的 λ(x)\lambda(x):两端为零,x=0x=0 处斜率 λx(0)=−142.66\lambda_x(0)=−142.66。
Figure 104 · L after the two integrations by parts. Three pieces (grey) are removed by the choice of λ: the interior by the adjoint equation, the two end terms λ(u u-ν u_x) by λ(0)=λ(1)=0, because u_x is unknown at the ends. The fourth piece (violet) contains only variations of the prescribed end values and stays in the gradient. In the middle, the actual λ(x) of the default design: zero at both ends, with the slope λ_x(0)=−142.66 at x=0.δℒ after integrating by parts twice: four pieces on [0,1]this page’s λ(x) (default design), λ = 0 at both endsx = 0x = 1λx​(0) = −142.7(steep: the layer)λx​(1) = 2.20x = 0: [λ(u δu − ν δux​)]δux​(0) unknown ⇒ λ(0) = 0this term vanishes✕interior: ∫[(1+x) − uλx​ − νλxx​] δuadjoint equation ⇒ integrand = 0this term vanishes✕x = 1: [λ(u δu − ν δux​)]δux​(1) unknown ⇒ λ(1) = 0this term vanishes✕ν[λx​ δu]0​1​ = ν λx​(1) δuout​ − ν λx​(0) δuin​δuin​, δuout​ are variations of given data: this term stays in the gradient✓
Figure 104 · δℒ\delta\mathcal L after the two integrations by parts. Three pieces (grey) are removed by the choice of λ\lambda: the interior by the adjoint equation, the two end terms λ(u δu−ν δux)\lambda(u\,\delta u-\nu\,\delta u_x) by λ(0)=λ(1)=0\lambda(0)=\lambda(1)=0, because δux\delta u_x is unknown at the ends. The fourth piece (violet) contains only variations of the prescribed end values and stays in the gradient. In the middle, the actual λ(x)\lambda(x) of the default design: zero at both ends, with the slope λx(0)=−142.66\lambda_x(0)=−142.66 at x=0x=0.

下面的播放器把这三步逐行算出来:取一个检验函数 vv 代替 δu\delta u,用本页的 λ\lambda 计算每一行的每一项。前六行对任何 vv 都相等(只用到分部积分和伴随方程);第七行还要用切线方程,所以只对真正的切线解成立。

The player below evaluates the three steps line by line: a test function vv stands in for δu\delta u, and every term of every line is computed with this page's λ\lambda. The first six lines agree for any vv (they use only integration by parts and the adjoint equation); the seventh also uses the tangent equation, so it holds only for a true tangent.

A.4 伴随问题适定吗:能证明的部分

A.4 Is the adjoint problem well posed? What can be proved

(A.3–A.4 中 vv 表示一般的函数——检验函数或 𝒜\mathcal A 定义域里的元素;vkv_k 才是切线解。)记状态线性算子 𝒜v=(uv−νvx)x\mathcal A v=(uv-\nu v_x)_x(带齐次端值 v(0)=v(1)=0v(0)=v(1)=0),伴随算子 𝒜∗λ=−uλx−νλxx\mathcal A^*\lambda=-u\lambda_x-\nu\lambda_{xx}(带 λ(0)=λ(1)=0\lambda(0)=\lambda(1)=0)。下面三条中,(1)、(3) 在本页完整证明;(2) 证明一个方向,另一方向引用 Fredholm 择一定理。它们对任何连续的 uu 和任何 ν>0\nu>0 成立,只有第三条要求 u>0u>0。

(In A.3–A.4, vv is a generic function, a test function or an element of the domain of 𝒜\mathcal A; the tangent is vkv_k.) Write the linear state operator 𝒜v=(uv−νvx)x\mathcal A v=(uv-\nu v_x)_x (with homogeneous end values v(0)=v(1)=0v(0)=v(1)=0) and the adjoint operator 𝒜∗λ=−uλx−νλxx\mathcal A^*\lambda=-u\lambda_x-\nu\lambda_{xx} (with λ(0)=λ(1)=0\lambda(0)=\lambda(1)=0). Of the three statements below, (1) and (3) are proved in full here; (2) proves one direction and cites the Fredholm alternative for the other. They hold for every continuous uu and every ν>0\nu>0, and only the third needs u>0u>0.

(1) 唯一可解。伴随方程对 λx\lambda_x 是一阶的:记 Φ(x)=ν−1∫0xu dt\Phi(x)=\nu^{-1}\int_0^xu\,\mathrm dt,则 νλxx+uλx=1+x\nu\lambda_{xx}+u\lambda_x=1+x 等价于 (eΦλx)x=eΦ(1+x)/ν\bigl(e^{\Phi}\lambda_x\bigr)_x=e^{\Phi}(1+x)/\nu。积分两次:

(1) Unique solvability. The adjoint equation is first order in λx\lambda_x: with Φ(x)=ν−1∫0xu dt\Phi(x)=\nu^{-1}\int_0^xu\,\mathrm dt, the equation νλxx+uλx=1+x\nu\lambda_{xx}+u\lambda_x=1+x is the same as (eΦλx)x=eΦ(1+x)/ν\bigl(e^{\Phi}\lambda_x\bigr)_x=e^{\Phi}(1+x)/\nu. Integrate twice:

λx(x)=e−Φ(x)[λx(0)+1ν∫0xeΦ(t)(1+t) dt],λ(x)=∫0xλx dt.\lambda_x(x)=e^{-\Phi(x)}\Bigl[\lambda_x(0)+\frac1\nu\int_0^xe^{\Phi(t)}(1+t)\,\mathrm dt\Bigr],\qquad \lambda(x)=\int_0^x\lambda_x\,\mathrm dt .

λ(0)=0\lambda(0)=0 已经满足;λ(1)=0\lambda(1)=0 是关于 λx(0)\lambda_x(0) 的一个线性方程,系数 ∫01e−Φ dx>0\int_0^1e^{-\Phi}\,\mathrm dx>0,所以 λx(0)\lambda_x(0) 唯一确定,解存在且唯一。右端项为零时同一计算给出 λx(0)=0\lambda_x(0)=0、λ≡0\lambda\equiv0:在这组边界条件下,伴随齐次问题只有零解。对 𝒜v=f\mathcal A v=f 积分一次得 uv−νvx=uv-\nu v_x= 常数 +∫0xf+\int_0^xf,同样的积分因子对任意连续的 ff 解出唯一的 vv(v(1)=0v(1)=0 确定那个常数):状态算子 𝒜\mathcal A 可逆。

λ(0)=0\lambda(0)=0 holds by construction; λ(1)=0\lambda(1)=0 is one linear equation for λx(0)\lambda_x(0) with the coefficient ∫01e−Φ dx>0\int_0^1e^{-\Phi}\,\mathrm dx>0, so λx(0)\lambda_x(0) is determined uniquely and the solution exists and is unique. With a zero right side the same computation gives λx(0)=0\lambda_x(0)=0 and λ≡0\lambda\equiv0: the adjoint operator has no nonzero homogeneous solution under these boundary conditions. Integrating 𝒜v=f\mathcal A v=f once gives uv−νvx=uv-\nu v_x= constant +∫0xf+\int_0^xf, and the same integrating factor solves it uniquely for every continuous ff (v(1)=0v(1)=0 fixes the constant): the state operator 𝒜\mathcal A is invertible.

(2) 为什么两者总是同时可逆(简短论证)。A.2 的分部积分在 v(0)=v(1)=0v(0)=v(1)=0、λ(0)=λ(1)=0\lambda(0)=\lambda(1)=0 时两端项全为零,剩下 Green 恒等式 ∫01λ 𝒜v dx=∫01(𝒜∗λ) v dx\int_0^1\lambda\,\mathcal A v\,\mathrm dx=\int_0^1(\mathcal A^*\lambda)\,v\,\mathrm dx。若 𝒜∗λ0=0\mathcal A^*\lambda_0=0 而 λ0≠0\lambda_0\ne0,则对所有 vv 有 ∫λ0𝒜v=0\int\lambda_0\mathcal Av=0:任何满足 ∫λ0f≠0\int\lambda_0 f\ne0 的右端项 ff 都不在 𝒜\mathcal A 的值域里,𝒜\mathcal A 不可逆。反方向(𝒜\mathcal A 不可逆 ⇒\Rightarrow 伴随有非零齐次解)是正则二阶边值问题的 Fredholm 择一定理,属于标准结论,本页不再证明;对本问题,(1) 已直接证明:状态算子与伴随算子的齐次问题都只有零解。离散的对应物是 AA 与 ATA^T 秩相同。

(2) Why the two are always invertible together (a short argument). With v(0)=v(1)=0v(0)=v(1)=0 and λ(0)=λ(1)=0\lambda(0)=\lambda(1)=0 every end term of the integration by parts of A.2 vanishes, and what is left is Green's identity ∫01λ 𝒜v dx=∫01(𝒜∗λ) v dx\int_0^1\lambda\,\mathcal A v\,\mathrm dx=\int_0^1(\mathcal A^*\lambda)\,v\,\mathrm dx. If 𝒜∗λ0=0\mathcal A^*\lambda_0=0 with λ0≠0\lambda_0\ne0, then ∫λ0𝒜v=0\int\lambda_0\mathcal Av=0 for every vv: no right side ff with ∫λ0f≠0\int\lambda_0 f\ne0 lies in the range of 𝒜\mathcal A, and 𝒜\mathcal A is not invertible. The converse (𝒜\mathcal A not invertible ⇒\Rightarrow a nonzero homogeneous solution of the adjoint problem) is the Fredholm alternative for regular second-order boundary-value problems, a standard result not re-proved here; for this problem (1) has already shown directly that the homogeneous state and adjoint problems have only the zero solution. The discrete counterpart is that AA and ATA^T have the same rank.

(3) 最大值原理(u>0u>0)。(a) 伴随方程的右端项 −(1+x)<0-(1+x)<0。在 λ\lambda 的内部极大点 λx=0\lambda_x=0、λxx≤0\lambda_{xx}\le0,于是 𝒜∗λ=−νλxx≥0\mathcal A^*\lambda=-\nu\lambda_{xx}\ge0,与 𝒜∗λ<0\mathcal A^*\lambda<0 矛盾;所以最大值只在两端取到,在 (0,1)(0,1) 上 λ<0\lambda<0(这一步不需要 uu 的符号)。(b) 若 u≥umin⁡>0u\ge u_{\min}>0,取常数 C>2/umin⁡C>2/u_{\min},则 𝒜∗(λ+C(1−x))=uC−(1+x)>0\mathcal A^*\bigl(\lambda+C(1-x)\bigr)=uC-(1+x)>0;同样的论证说明 λ+C(1−x)\lambda+C(1-x) 没有内部极小,它的最小值在端点取到:x=0x=0 处是 C>0C>0,x=1x=1 处是 00,所以最小值是 00。令 C→2/umin⁡C\to2/u_{\min}:

(3) The maximum principle (u>0u>0). (a) The right side of the adjoint equation, −(1+x)-(1+x), is negative. At an interior maximum of λ\lambda, λx=0\lambda_x=0 and λxx≤0\lambda_{xx}\le0, so 𝒜∗λ=−νλxx≥0\mathcal A^*\lambda=-\nu\lambda_{xx}\ge0, contradicting 𝒜∗λ<0\mathcal A^*\lambda<0; hence the maximum is attained only at the ends and λ<0\lambda<0 on (0,1)(0,1) (this step needs no sign of uu). (b) If u≥umin⁡>0u\ge u_{\min}>0, take a constant C>2/umin⁡C>2/u_{\min}; then 𝒜∗(λ+C(1−x))=uC−(1+x)>0\mathcal A^*\bigl(\lambda+C(1-x)\bigr)=uC-(1+x)>0, and the same argument shows that λ+C(1−x)\lambda+C(1-x) has no interior minimum: its minimum is attained at an end: the value is C>0C>0 at x=0x=0 and 00 at x=1x=1, so the minimum is 00. Letting C→2/umin⁡C\to2/u_{\min},

−2umin⁡ (1−x)≤λ(x)<0(0<x<1),对每个 ν>0.-\frac{2}{u_{\min}}\,(1-x)\le\lambda(x)<0\qquad(0<x<1),\quad\text{对每个 }\nu>0 .
−2umin⁡ (1−x)≤λ(x)<0(0<x<1),for every ν>0.-\frac{2}{u_{\min}}\,(1-x)\le\lambda(x)<0\qquad(0<x<1),\quad\text{for every }\nu>0 .

默认设计 umin⁡=1−a=0.8u_{\min}=1-a=0.8,下界是 −2.5(1−x)-2.5(1-x),即 ∣λ∣≤2.5(1−x)|\lambda|\le2.5(1-x)。它与 ν\nu 无关:ν→0\nu\to0 时 λ\lambda 本身保持有界,变陡的只是 x=0x=0 处的斜率——那是一个边界层,不是 λ\lambda 的爆破。本附录中各个 ν\nu 的解都满足这两个不等式(check_g.js 逐点检查)。

At the defaults umin⁡=1−a=0.8u_{\min}=1-a=0.8 and the lower bound is −2.5(1−x)-2.5(1-x), i.e. ∣λ∣≤2.5(1−x)|\lambda|\le2.5(1-x). It does not depend on ν\nu: as ν→0\nu\to0 the function λ\lambda itself stays bounded, and only its slope at x=0x=0 steepens. That is a boundary layer, not a blow-up of λ\lambda. Every solution of this appendix, for every ν\nu, satisfies the two inequalities (checked point by point by check_g.js).

本页没有证明的:离散伴随 ψ\psi 收敛到 λ\lambda(第 16 节与 A.7 给的是数值证据);下面 A.6 的渐近展开(形式推导,用数值核对);uu 变号或出现激波时的任何结论。

Not proved on this page: the convergence of the discrete adjoint ψ\psi to λ\lambda (Section 16 and A.7 give numerical evidence); the asymptotic expansion of A.6 below (a formal derivation, checked numerically); anything for a uu that changes sign or contains a shock.

A.5 求解:本页的谱方法

A.5 Solving it: the page’s spectral solver

model.js 的 continuousAdjoint(D, M) 用 Chebyshev 配点法解这个两点边值问题:取 M+1M+1 个点 xk=12(1+cos⁡(πk/M))x_k=\tfrac12\bigl(1+\cos(\pi k/M)\bigr)——它们在两端加密,正好落在边界层里;对过这些点的插值多项式求导,得到微分矩阵 𝖣(1)\mathsf D^{(1)} 与 𝖣(2)=(𝖣(1))2\mathsf D^{(2)}=(\mathsf D^{(1)})^2(无衬线的 𝖣\mathsf D 不是设计 DD);在内部点上要求 −u(xk)(𝖣(1)λ)k−ν(𝖣(2)λ)k=−(1+xk)-u(x_k)(\mathsf D^{(1)}\lambda)_k-\nu(\mathsf D^{(2)}\lambda)_k=-(1+x_k),两端点上 λ=0\lambda=0;解一个稠密线性方程组,λx\lambda_x 由 𝖣(1)λ\mathsf D^{(1)}\lambda 给出。它与有限体积模型只共用稠密 LU(experiments/numerics.js)和 u∗u^* 的公式;离散方法(配点)与有限体积、与离散伴随无关。不共用方法的核对是下面的积分因子公式(不用配点,也不用 LU),以及附录 B 的 check_dn.py(用 ODE 积分器打靶)。Python 审计 audit/audit_g.py 里的 NumPy 求解器是同一种配点法的重新实现:它检验代码,不检验方法。

continuousAdjoint(D, M) of model.js solves this two-point boundary-value problem by Chebyshev collocation: take the M+1M+1 points xk=12(1+cos⁡(πk/M))x_k=\tfrac12\bigl(1+\cos(\pi k/M)\bigr), which cluster at both ends, right inside the boundary layer; differentiating the interpolating polynomial through them gives the differentiation matrices 𝖣(1)\mathsf D^{(1)} and 𝖣(2)=(𝖣(1))2\mathsf D^{(2)}=(\mathsf D^{(1)})^2 (the sans-serif 𝖣\mathsf D is not the design DD); require −u(xk)(𝖣(1)λ)k−ν(𝖣(2)λ)k=−(1+xk)-u(x_k)(\mathsf D^{(1)}\lambda)_k-\nu(\mathsf D^{(2)}\lambda)_k=-(1+x_k) at the interior points and λ=0\lambda=0 at the two end points; solve one dense linear system, and read λx\lambda_x from 𝖣(1)λ\mathsf D^{(1)}\lambda. With the finite-volume model it shares only the dense LU (experiments/numerics.js) and the formula of u∗u^*; its discretisation (collocation) has nothing to do with the finite volumes or the discrete adjoint. The checks that do not share the method are the integrating-factor formula below (no collocation, no LU) and, for Appendix B, check_dn.py (shooting with an ODE integrator). The NumPy solver of the Python audit (audit/audit_g.py) is the same collocation written again: it checks the code, not the method.

收敛性:在 401 个采样点上,M=160M=160 与 M=320M=320 的 λ\lambda 最大相差不到 3e−13,λx(0)\lambda_x(0) 的相对差不到 3e−13。另一条完全独立的路径是 A.4 的积分因子公式,用 Gauss 求积直接计算:它与谱方法的 λx(0)\lambda_x(0) 相对差不到 2e−14。Python 审计 audit/audit_g.py 用 NumPy 比较 M=240M=240 与 M=480M=480(同一种配点法,所以这检验代码与收敛,不检验方法)。本附录正文与图里伴随的数值用 M=240M=240;切线问题用 M=160M=160;本页其余各节用 M=200M=200(201 个点,model.js 的默认值):M=200M=200 与 M=240M=240 的 λ\lambda 最大相差不到 2e−13,λx(0)\lambda_x(0) 的相对差不到 4e−14,所以那里打印的数字与本附录在所示位数上一致;实验台按 ν\nu 选 MM(96 到 256,保证边界层被分辨,见 check_g.js)。

Convergence: on 401 sample points, λ\lambda for M=160M=160 and M=320M=320 differs by at most 3e−13, and λx(0)\lambda_x(0) by at most 3e−13 relative. A second, completely independent path is the integrating-factor formula of A.4, evaluated by Gauss quadrature: its λx(0)\lambda_x(0) agrees with the spectral one to within 2e−14 relative. The Python audit audit/audit_g.py compares M=240M=240 with M=480M=480 in NumPy (the same collocation, so this checks the code and the convergence, not the method). The adjoint numbers in the text and figures of this appendix use M=240M=240; the tangent problems use M=160M=160; the other sections of this page use M=200M=200 (201 points, the default of model.js): λ\lambda for M=200M=200 and M=240M=240 differs by at most 2e−13, and λx(0)\lambda_x(0) by at most 4e−14 relative, so the numbers printed there agree with this appendix to the digits shown; the labs choose MM from ν\nu (96 to 256, enough to resolve the layer, as check_g.js verifies).

默认设计下 λx(0)=−142.6568\lambda_x(0)=−142.6568、λx(1)=2.2035\lambda_x(1)=2.2035。把梯度公式逐项算出(Clenshaw–Curtis 求积,用同一组点):“源项积分”是 −∫01λ ∂s/∂Dk dx-\int_0^1\lambda\,\partial s/\partial D_k\,\mathrm dx(对 ν\nu 是 −∫01λ sν dx-\int_0^1\lambda\,s_\nu\,\mathrm dx,与图 106 右图相同;这一行的第三列放通量项 −∫01λ uxx dx-\int_0^1\lambda\,u_{xx}\,\mathrm dx),“边界项”是 ν(λx(1) ∂uout/∂Dk−λx(0) ∂uin/∂Dk)\nu\bigl(\lambda_x(1)\,\partial u_{\rm out}/\partial D_k-\lambda_x(0)\,\partial u_{\rm in}/\partial D_k\bigr)。

At the defaults λx(0)=−142.6568\lambda_x(0)=−142.6568 and λx(1)=2.2035\lambda_x(1)=2.2035. The gradient formula term by term (Clenshaw–Curtis quadrature on the same points): the source integral is −∫01λ ∂s/∂Dk dx-\int_0^1\lambda\,\partial s/\partial D_k\,\mathrm dx (for ν\nu, −∫01λ sν dx-\int_0^1\lambda\,s_\nu\,\mathrm dx, as in the right panel of Figure 106, with the flux term −∫01λ uxx dx-\int_0^1\lambda\,u_{xx}\,\mathrm dx in the third column of that row), the boundary term ν(λx(1) ∂uout/∂Dk−λx(0) ∂uin/∂Dk)\nu\bigl(\lambda_x(1)\,\partial u_{\rm out}/\partial D_k-\lambda_x(0)\,\partial u_{\rm in}/\partial D_k\bigr).

分量Component源项积分Source integral边界项Boundary term和Sum精确梯度Exact gradient和与精确之差Sum minus exact
aa0.472777−0.616785−0.144007698−0.144007698−6e−14
φ\varphi1.732274−1.6471180.0851558580.0851558581e−15
ν\nu1.876920−1.876920000

细看这张表。源项积分和边界项各自是 O(1)O(1) 的量,和却小得多:φ\varphi 的两部分(1.73、−1.65)约是和的 20 倍,几乎抵消;aa 的两部分(0.47、−0.62)约是和的 3.3–4.3 倍;和与精确值相差不到 7e−14。所以边界项不能省:省掉它,φ\varphi 分量会错二十倍。

Read the table carefully. The source integral and the boundary term are each of order one while their sum is much smaller: for φ\varphi the two parts (1.73 and −1.65) are about 20 times the sum and nearly cancel; for aa (0.47 and −0.62) they are about 3.3–4.3 times the sum; the sums agree with the exact values to within 7e−14. So the boundary term cannot be dropped: without it the φ\varphi component would be wrong by a factor of twenty.

图 105 · 连续伴随 λ(x),四个黏性系数(谱方法,M=240,a=0.2,φ=0.07)。左:整个区间;虚线是外解 λ_out(νλ_xx 略去,从 x=1 积分)。右:放大 x=0 附近,点线是 ν=0.01 的复合近似 λ_out(x)-λ_out(0)e^-u_inx/ν。ν 每减小到原来的十分之一,层宽也减小到十分之一,斜率则增大到十倍;层变薄以后 λ 的大小变化不大:ν=0.1、0.03、0.01、0.003 时最小值为 −1.08、−1.37、−1.48、−1.53,趋于 λ_out(0)=−1.56。ν = 0.1ν = 0.03ν = 0.01ν = 0.003λout​(外解)复合近似(ν = 0.01)−1.6−1.4−1.2−1−0.8−0.6−0.4−0.2000.20.40.60.81xλ整个区间−1.6−1.4−1.2−1−0.8−0.6−0.4−0.2000.010.020.030.040.050.06x放大 x ∈ [0, 0.06]:x = 0 处的层ν = 0.01:λx​(0) = −142.7
图 105 · 连续伴随 λ(x)\lambda(x),四个黏性系数(谱方法,M=240M=240,a=0.2a=0.2,φ=0.07\varphi=0.07)。左:整个区间;虚线是外解 λout\lambda_{\rm out}(νλxx\nu\lambda_{xx} 略去,从 x=1x=1 积分)。右:放大 x=0x=0 附近,点线是 ν=0.01\nu=0.01 的复合近似 λout(x)−λout(0)e−uinx/ν\lambda_{\rm out}(x)-\lambda_{\rm out}(0)e^{-u_{\rm in}x/\nu}。ν\nu 每减小到原来的十分之一,层宽也减小到十分之一,斜率则增大到十倍;层变薄以后 λ\lambda 的大小变化不大:ν=0.1\nu=0.1、0.030.03、0.010.01、0.0030.003 时最小值为 −1.08、−1.37、−1.48、−1.53,趋于 λout(0)=−1.56\lambda_{\rm out}(0)=−1.56。
Figure 105 · The continuous adjoint λ(x) for four viscosities (spectral solver, M=240, a=0.2, φ=0.07). Left: the whole interval; dashed, the outer solution λ_out (νλ_xx dropped, integrated from x=1). Right: zoom near x=0; dotted, the composite approximation λ_out(x)-λ_out(0)e^-u_inx/ν for ν=0.01. Each tenfold decrease of ν makes the layer ten times thinner and the slope ten times steeper; the size of λ changes little once the layer is thin: its minimum is −1.08, −1.37, −1.48, −1.53 for ν=0.1, 0.03, 0.01, 0.003, approaching λ_out(0)=−1.56.ν = 0.1ν = 0.03ν = 0.01ν = 0.003λout​ (outer)composite (ν = 0.01)−1.6−1.4−1.2−1−0.8−0.6−0.4−0.2000.20.40.60.81xλthe whole interval−1.6−1.4−1.2−1−0.8−0.6−0.4−0.2000.010.020.030.040.050.06xzoom x ∈ [0, 0.06]: the layer at x = 0ν = 0.01: λx​(0) = −142.7
Figure 105 · The continuous adjoint λ(x)\lambda(x) for four viscosities (spectral solver, M=240M=240, a=0.2a=0.2, φ=0.07\varphi=0.07). Left: the whole interval; dashed, the outer solution λout\lambda_{\rm out} (νλxx\nu\lambda_{xx} dropped, integrated from x=1x=1). Right: zoom near x=0x=0; dotted, the composite approximation λout(x)−λout(0)e−uinx/ν\lambda_{\rm out}(x)-\lambda_{\rm out}(0)e^{-u_{\rm in}x/\nu} for ν=0.01\nu=0.01. Each tenfold decrease of ν\nu makes the layer ten times thinner and the slope ten times steeper; the size of λ\lambda changes little once the layer is thin: its minimum is −1.08, −1.37, −1.48, −1.53 for ν=0.1\nu=0.1, 0.030.03, 0.010.01, 0.0030.003, approaching λout(0)=−1.56\lambda_{\rm out}(0)=−1.56.
图 106 · 梯度的两部分随 ν 的变化(每个 ν 一次谱方法求解)。左、中:a 与 φ 的源项积分(蓝)与边界项(紫)都是 O(1) 且随 ν 变化,它们的和(红圈)始终落在与 ν 无关的精确梯度(点线)上。右:ν 分量的源项积分与通量项大小相等、符号相反,和为零。源项积分 −∫λ ∂s/∂Dk​边界项 ν[λx​ ∂ub​/∂Dk​]ν 的通量项 −∫λ uxx​两项之和 = dJ/dDk​点线:精确梯度(与 ν 无关)−0.6−0.4−0.200.20.40.60.0010.010.1νD0​ = a−2−10120.0010.010.1νD1​ = φ−2−10120.0010.010.1νD2​ = ν
图 106 · 梯度的两部分随 ν\nu 的变化(每个 ν\nu 一次谱方法求解)。左、中:aa 与 φ\varphi 的源项积分(蓝)与边界项(紫)都是 O(1)O(1) 且随 ν\nu 变化,它们的和(红圈)始终落在与 ν\nu 无关的精确梯度(点线)上。右:ν\nu 分量的源项积分与通量项大小相等、符号相反,和为零。
Figure 106 · The two parts of the gradient as ν varies (one spectral solve per ν). Left and middle: for a and φ the source integral (blue) and the boundary term (violet) are both of order one and change with ν, while their sum (red rings) stays on the exact gradient (dotted), which does not depend on ν. Right: for the ν component the source integral and the flux term are equal and opposite and sum to zero.source integral −∫λ ∂s/∂Dk​boundary term ν[λx​ ∂ub​/∂Dk​]flux term of ν, −∫λ uxx​sum = dJ/dDk​dotted: the exact gradient (independent of ν)−0.6−0.4−0.200.20.40.60.0010.010.1νD0​ = a−2−10120.0010.010.1νD1​ = φ−2−10120.0010.010.1νD2​ = ν
Figure 106 · The two parts of the gradient as ν\nu varies (one spectral solve per ν\nu). Left and middle: for aa and φ\varphi the source integral (blue) and the boundary term (violet) are both of order one and change with ν\nu, while their sum (red rings) stays on the exact gradient (dotted), which does not depend on ν\nu. Right: for the ν\nu component the source integral and the flux term are equal and opposite and sum to zero.

在任意设计下检查对偶:用本附录自己的配点法解三个连续切线问题,再与伴随公式比较。

Check the duality at any design: solve the three continuous tangent problems with this appendix's own collocation and compare with the adjoint formula.

默认设计下(切线问题取 M=160M=160),切线解与精确导数 ∂u∗/∂Dk\partial u^*/\partial D_k(sin⁡z\sin z、−2πacos⁡z-2\pi a\cos z、00)相差不到 2e−13;两条路径给出同一个导数:

At the defaults (tangent problems with M=160M=160) the tangent solutions agree with the exact derivatives ∂u∗/∂Dk\partial u^*/\partial D_k (sin⁡z\sin z, −2πacos⁡z-2\pi a\cos z, 00) to better than 2e−13, and the two paths give the same derivative:

分量Component切线解 ∫01(1+x) vk dx\int_0^1(1+x)\,v_k\,\mathrm dxTangent ∫01(1+x) vk dx\int_0^1(1+x)\,v_k\,\mathrm dx伴随公式Adjoint formula两者之差Difference切线解的误差Error of the tangent
aa−0.1440076980−0.14400769805e−141e−13
φ\varphi0.08515585830.08515585832e−132e−13
ν\nu0.00000000000.000000000000
∫01(1+x) vk dx=−∫01λ ∂s∂Dk dx+ν[λxvk]01.\int_0^1(1+x)\,v_k\,\mathrm dx=-\int_0^1\lambda\,\frac{\partial s}{\partial D_k}\,\mathrm dx+\nu\bigl[\lambda_x v_k\bigr]_0^1 .

这就是连续层次的对偶恒等式:左边一次切线求解给一个分量,右边一次伴随求解给全部分量。它与离散的 RˉTR˙=𝐔ˉT𝐔˙+DˉTD˙\bar R^T\dot R=\bar{\mathbf U}^T\dot{\mathbf U}+\bar D^T\dot D 是同一件事:分部积分扮演了转置的角色。

This is the duality identity at the continuous level: on the left one tangent solve gives one component, on the right one adjoint solve gives all of them. It is the same thing as the discrete RˉTR˙=𝐔ˉT𝐔˙+DˉTD˙\bar R^T\dot R=\bar{\mathbf U}^T\dot{\mathbf U}+\bar D^T\dot D, with integration by parts playing the role of the transpose.

A.6 x = 0 处的边界层

A.6 The boundary layer at x = 0

为什么层在 x=0x=0?伴随的对流项 −uλx-u\lambda_x(u>0u>0)把信息从 x=1x=1 带向 x=0x=0——与流动方向相反。所以 x=1x=1 是伴随的“上游”,x=0x=0 的条件只能靠一个薄层来满足。

Why is the layer at x=0x=0? The adjoint convection term −uλx-u\lambda_x (with u>0u>0) carries information from x=1x=1 towards x=0x=0, against the flow. So x=1x=1 is upstream for the adjoint, and the condition at x=0x=0 can only be met through a thin layer.

外解。略去 νλxx\nu\lambda_{xx},得 −uλx=−(1+x)-u\lambda_x=-(1+x);从上游端 λout(1)=0\lambda_{\rm out}(1)=0 积分,得

Outer solution. Drop νλxx\nu\lambda_{xx}: −uλx=−(1+x)-u\lambda_x=-(1+x), integrated from the upstream end λout(1)=0\lambda_{\rm out}(1)=0:

λout(x)=−∫x11+tu(t) dt,λout(0)=−∫011+tu(t) dt=−1.561867.\lambda_{\rm out}(x)=-\int_x^1\frac{1+t}{u(t)}\,\mathrm dt,\qquad \lambda_{\rm out}(0)=-\int_0^1\frac{1+t}{u(t)}\,\mathrm dt=−1.561867.

内解。在 x=0x=0 附近 u≈uinu\approx u_{\rm in},层内 λ\lambda 变化快、1+x1+x 的作用可略,方程近似为 −uinλx−νλxx=0-u_{\rm in}\lambda_x-\nu\lambda_{xx}=0,解为 C1+C2e−uinx/νC_1+C_2e^{-u_{\rm in}x/\nu}。要求 λ(0)=0\lambda(0)=0、在层外与外解匹配,得复合近似:

Inner solution. Near x=0x=0, u≈uinu\approx u_{\rm in}; inside the layer λ\lambda varies fast and the source 1+x1+x is negligible, so the equation is approximately −uinλx−νλxx=0-u_{\rm in}\lambda_x-\nu\lambda_{xx}=0, whose solutions are C1+C2e−uinx/νC_1+C_2e^{-u_{\rm in}x/\nu}. Requiring λ(0)=0\lambda(0)=0 and a match with the outer solution outside the layer gives the composite approximation:

λ(x)≈λout(x)−λout(0) e−uinx/ν⟹λx(0)≈uinλout(0)ν,νλx(0)→uinλout(0)=−1.428865.\lambda(x)\approx\lambda_{\rm out}(x)-\lambda_{\rm out}(0)\,e^{-u_{\rm in}x/\nu}\quad\Longrightarrow\quad \lambda_x(0)\approx\frac{u_{\rm in}\lambda_{\rm out}(0)}{\nu},\qquad \nu\lambda_x(0)\to u_{\rm in}\lambda_{\rm out}(0)=−1.428865.

实验的答案:νλx(0)\nu\lambda_x(0) 趋于一个非零常数,所以边界项 −νλx(0) ∂uin/∂Dk-\nu\lambda_x(0)\,\partial u_{\rm in}/\partial D_k 在 ν→0\nu\to0 时不消失,而是趋于 −uinλout(0) ∂uin/∂Dk-u_{\rm in}\lambda_{\rm out}(0)\,\partial u_{\rm in}/\partial D_k。这也解释了离散的情形:本页网格上入口行 R0=U0−uinR_0=U_0-u_{\rm in} 是约束,它的乘子 ψ0\psi_0 在梯度里乘 −∂uin/∂Dk-\partial u_{\rm in}/\partial D_k,所以 −ψ0 ∂uin/∂Dk-\psi_0\,\partial u_{\rm in}/\partial D_k 就是 −νλx(0) ∂uin/∂Dk-\nu\lambda_x(0)\,\partial u_{\rm in}/\partial D_k 的离散对应,ψ0\psi_0 本身逼近 νλx(0)\nu\lambda_x(0)(A.7)。它不是 λ\lambda 的某个节点值,也不必除以网格间距。在默认设计下,要得到接近 νλx(0)\nu\lambda_x(0) 的 ψ0\psi_0,网格不必分辨边界层:N=8N=8 时第一个区间是层宽 ν/uin\nu/u_{\rm in} 的 11.4 倍,而 ψ0\psi_0 与 νλx(0)\nu\lambda_x(0) 的相对差,无限制器线性是 1.4%(A.7),一阶是 1.2%,光滑限制器是 5.4%。这是该设计下的观察,不是普遍规律(见第 16 节)。

The answer to the experiment: νλx(0)\nu\lambda_x(0) tends to a nonzero constant, so the boundary term −νλx(0) ∂uin/∂Dk-\nu\lambda_x(0)\,\partial u_{\rm in}/\partial D_k does not vanish as ν→0\nu\to0; it tends to −uinλout(0) ∂uin/∂Dk-u_{\rm in}\lambda_{\rm out}(0)\,\partial u_{\rm in}/\partial D_k. This also explains the discrete picture. On this page's mesh the inlet row R0=U0−uinR_0=U_0-u_{\rm in} is a constraint; its multiplier ψ0\psi_0 multiplies −∂uin/∂Dk-\partial u_{\rm in}/\partial D_k in the gradient, so −ψ0 ∂uin/∂Dk-\psi_0\,\partial u_{\rm in}/\partial D_k is the discrete counterpart of −νλx(0) ∂uin/∂Dk-\nu\lambda_x(0)\,\partial u_{\rm in}/\partial D_k, and ψ0\psi_0 itself approximates νλx(0)\nu\lambda_x(0) (A.7). It is not a nodal value of λ\lambda and needs no division by a mesh width. At the default design, getting ψ0\psi_0 close to νλx(0)\nu\lambda_x(0) does not require a mesh that resolves the layer: at N=8N=8 the first interval is 11.4 times the layer width ν/uin\nu/u_{\rm in}, and the relative difference between ψ0\psi_0 and νλx(0)\nu\lambda_x(0) is 1.4% for the unlimited linear reconstruction (A.7), 1.2% for first order and 5.4% for the smooth limiter. This is an observation at this design, not a rule (Section 16).

误差有多大。由 A.4,λx(0)\lambda_x(0) 的精确表达式为 λx(0)=−∫01Π dx/∫01e−Φ dx\lambda_x(0)=-\int_0^1\Pi\,\mathrm dx\big/\int_0^1e^{-\Phi}\,\mathrm dx(Π\Pi 是 A.4 积分因子公式里 λx(0)=0\lambda_x(0)=0 时的 λx\lambda_x)。对两个积分分别展开——分母用 Laplace 方法,∫01e−Φ=νuin(1−νux(0)/uin2+O(ν2))\int_0^1e^{-\Phi}=\tfrac{\nu}{u_{\rm in}}\bigl(1-\nu u_x(0)/u_{\rm in}^2+O(\nu^2)\bigr);分子用外展开加端点修正——得到两项形式渐近展开

How large is the error. The exact formula is λx(0)=−∫01Π dx/∫01e−Φ dx\lambda_x(0)=-\int_0^1\Pi\,\mathrm dx\big/\int_0^1e^{-\Phi}\,\mathrm dx, where Π\Pi is the λx\lambda_x of the integrating-factor formula of A.4 with λx(0)=0\lambda_x(0)=0. Expanding the two integrals separately (Laplace's method for the denominator, ∫01e−Φ=νuin(1−νux(0)/uin2+O(ν2))\int_0^1e^{-\Phi}=\tfrac{\nu}{u_{\rm in}}\bigl(1-\nu u_x(0)/u_{\rm in}^2+O(\nu^2)\bigr); an outer expansion with an end correction for the numerator) gives the formal two-term expansion

νλx(0)=uinλout(0)+γ1ν+O(ν2),γ1=uin[∫011u(1+xu)xdx+1uin2]+λout(0) ux(0)uin=0.18472.\nu\lambda_x(0)=u_{\rm in}\lambda_{\rm out}(0)+\gamma_1\nu+O(\nu^2),\qquad \gamma_1=u_{\rm in}\Bigl[\int_0^1\frac1u\Bigl(\frac{1+x}{u}\Bigr)_x\mathrm dx+\frac1{u_{\rm in}^2}\Bigr]+\frac{\lambda_{\rm out}(0)\,u_x(0)}{u_{\rm in}}=0.18472.

下表用谱方法核对(每个 ν\nu 一次求解):一项近似的误差除以 ν\nu 趋于 γ1\gamma_1,两项近似的剩余除以 ν2\nu^2 保持有界。默认 ν=0.01\nu=0.01 时一项近似差 2.3e−3(约 0.16%)。

The table checks this against the spectral solver (one solve per ν\nu): the error of the one-term approximation divided by ν\nu tends to γ1\gamma_1, and the remainder of the two-term approximation divided by ν2\nu^2 stays bounded. At the default ν=0.01\nu=0.01 the one-term approximation is off by 2.3e−3 (about 0.16%).

ν\nuλx(0)\lambda_x(0)νλx(0)\nu\lambda_x(0)νλx(0)−uinλout(0)\nu\lambda_x(0)-u_{\rm in}\lambda_{\rm out}(0)误差 /ν/\nuerror /ν/\nu两项后误差 /ν2/\nu^2after two terms /ν2/\nu^2
0.1−13.5304−1.3530427.58e−20.75825.74
0.03−47.2758−1.4182731.06e−20.35315.61
0.01−142.6568−1.4265682.30e−30.22974.50
0.003−476.0922−1.4282775.89e−40.19623.82
0.001−1428.6769−1.4286771.88e−40.18833.59
图 107 · 边界层的渐近核对。左:νλ_x(0)(点)趋于 u_inλ_out(0)=−1.4289(虚线),紫色点线是两项展开 u_inλ_out(0)+γ_1ν。右:一项近似的误差按 ν 下降,两项近似的误差按 ν^2 下降。数值证据,不是证明。−1.45−1.4−1.35−1.3−1.25−1.20.0010.010.1νν λx​(0)边界项的系数保持 O(1)谱方法解uin​ λout​(0)两项展开10-6​10-5​10-4​10-3​10-2​10-1​10.0010.010.1ν误差渐近式的误差一项:∝ ν两项:∝ ν²
图 107 · 边界层的渐近核对。左:νλx(0)\nu\lambda_x(0)(点)趋于 uinλout(0)=−1.4289u_{\rm in}\lambda_{\rm out}(0)=−1.4289(虚线),紫色点线是两项展开 uinλout(0)+γ1νu_{\rm in}\lambda_{\rm out}(0)+\gamma_1\nu。右:一项近似的误差按 ν\nu 下降,两项近似的误差按 ν2\nu^2 下降。数值证据,不是证明。
Figure 107 · The boundary-layer asymptotics checked. Left: νλ_x(0) (dots) tends to u_inλ_out(0)=−1.4289 (dashed); the violet dotted line is the two-term expansion u_inλ_out(0)+γ_1ν. Right: the error of the one-term approximation falls like ν, that of the two-term approximation like ν^2. Numerical evidence, not a proof.−1.45−1.4−1.35−1.3−1.25−1.20.0010.010.1νν λx​(0)the boundary coefficient stays O(1)spectral solveuin​ λout​(0)two terms10-6​10-5​10-4​10-3​10-2​10-1​10.0010.010.1νerrorerror of the asymptoticsone term: ∝ νtwo terms: ∝ ν²
Figure 107 · The boundary-layer asymptotics checked. Left: νλx(0)\nu\lambda_x(0) (dots) tends to uinλout(0)=−1.4289u_{\rm in}\lambda_{\rm out}(0)=−1.4289 (dashed); the violet dotted line is the two-term expansion uinλout(0)+γ1νu_{\rm in}\lambda_{\rm out}(0)+\gamma_1\nu. Right: the error of the one-term approximation falls like ν\nu, that of the two-term approximation like ν2\nu^2. Numerical evidence, not a proof.

自己调 ν\nu:实验台每次用本页的谱方法重新求解,画出 λ\lambda、层内放大与复合近似,并给出 λx(0)\lambda_x(0)、νλx(0)\nu\lambda_x(0) 和梯度的两部分。

Move ν\nu yourself: the lab re-solves with this page's spectral solver each time, draws λ\lambda, the zoom into the layer with the composite approximation, and reports λx(0)\lambda_x(0), νλx(0)\nu\lambda_x(0) and the two parts of the gradient.

播放器把 ν\nu 从 0.2 一步步减到 0.001:看层怎样变薄,νλx(0)\nu\lambda_x(0) 的点怎样落到渐近线上,而梯度的和始终不变。

The player lowers ν\nu step by step from 0.2 to 0.001: watch the layer thin, the points of νλx(0)\nu\lambda_x(0) settle onto the asymptote, and the sum of the gradient stay put.

A.7 离散的对应:本页网格上的伴随

A.7 The discrete counterpart on this page’s mesh

第 9、11 节的离散伴随解 ATψ=−gA^T\psi=-g(g=wg=w),梯度是 dJh/dD=RDTψ\mathrm dJ_h/\mathrm dD=R_D^T\psi。把这个乘积按行拆开。两个约束行对设计的依赖只经过边界数据,(RD)0k=−∂uin/∂Dk(R_D)_{0k}=-\partial u_{\rm in}/\partial D_k、(RD)Nk=−∂uout/∂Dk(R_D)_{Nk}=-\partial u_{\rm out}/\partial D_k,所以

The discrete adjoint of Sections 9 and 11 solves ATψ=−gA^T\psi=-g (g=wg=w) and gives the gradient dJh/dD=RDTψ\mathrm dJ_h/\mathrm dD=R_D^T\psi. Split that product by rows. The two constraint rows depend on the design only through the boundary data, (RD)0k=−∂uin/∂Dk(R_D)_{0k}=-\partial u_{\rm in}/\partial D_k and (RD)Nk=−∂uout/∂Dk(R_D)_{Nk}=-\partial u_{\rm out}/\partial D_k, so

dJhdDk=∑j=1N−1ψj (RD)jk  −  ψ0 ∂uin∂Dk  −  ψN ∂uout∂Dk.\frac{\mathrm dJ_h}{\mathrm dD_k}=\sum_{j=1}^{N-1}\psi_j\,(R_D)_{jk}\;-\;\psi_0\,\frac{\partial u_{\rm in}}{\partial D_k}\;-\;\psi_N\,\frac{\partial u_{\rm out}}{\partial D_k}.

内部行之和对应 A.3 的源项积分 −∫01λ ∂s/∂Dk dx-\int_0^1\lambda\,\partial s/\partial D_k\,\mathrm dx(对偶控制体 VjV_j 的行里放的是源项在它上面的精确积分,ψj\psi_j 扮演 λ(xj)\lambda(x_j));剩下两项对应边界项 ν(λx(1) ∂uout/∂Dk−λx(0) ∂uin/∂Dk)\nu\bigl(\lambda_x(1)\,\partial u_{\rm out}/\partial D_k-\lambda_x(0)\,\partial u_{\rm in}/\partial D_k\bigr),其中 ψ0↔νλx(0)\psi_0\leftrightarrow\nu\lambda_x(0),ψN↔−νλx(1)\psi_N\leftrightarrow-\nu\lambda_x(1)。(对 ν\nu 分量,内部行之和还带着 A.3 的通量项,没有边界部分。)所以约束行的乘子就是整个边界项:不必再从边界面上补任何东西。

The sum over the interior rows is the counterpart of the source integral −∫01λ ∂s/∂Dk dx-\int_0^1\lambda\,\partial s/\partial D_k\,\mathrm dx of A.3 (the row of the dual volume VjV_j holds the exact integral of the source over it, and ψj\psi_j plays the role of λ(xj)\lambda(x_j)); the two remaining terms are the counterpart of the boundary term ν(λx(1) ∂uout/∂Dk−λx(0) ∂uin/∂Dk)\nu\bigl(\lambda_x(1)\,\partial u_{\rm out}/\partial D_k-\lambda_x(0)\,\partial u_{\rm in}/\partial D_k\bigr), with ψ0↔νλx(0)\psi_0\leftrightarrow\nu\lambda_x(0) and ψN↔−νλx(1)\psi_N\leftrightarrow-\nu\lambda_x(1). (For the component ν\nu the interior sum also carries the flux term of A.3, and there is no boundary part.) The multiplier of a constraint row is therefore the whole boundary term: nothing has to be added from a boundary face.

为什么可以把 ψj\psi_j 直接与 λ(xj)\lambda(x_j) 比较,符号相同、也没有网格宽度的因子?第 5 节的行是对偶控制体上的积分:Rj=Hj−Hj−1−(Qj−Qj−1)R_j=H_j-H_{j-1}-(Q_j-Q_{j-1}) 是流出 VjV_j 的数值通量净值减去源项在 VjV_j 上的精确积分,所以 Rj≈∫Vj(qx−s) dxR_j\approx\int_{V_j}(q_x-s)\,\mathrm dx,而 wjUj≈∫Vj(1+x) u dxw_jU_j\approx\int_{V_j}(1+x)\,u\,\mathrm dx。于是 ψj≈λ(xj)\psi_j\approx\lambda(x_j) 时 Jh+ψTR≈J+∫01λ (qx−s) dxJ_h+\psi^TR\approx J+\int_0^1\lambda\,(q_x-s)\,\mathrm dx,与 A.2 一致。(附录 B 的行除以了 hh,那里 ψj≈h λ(xj)\psi_j\approx h\,\lambda(x_j):ψ\psi 的缩放跟着行的缩放走。)约束行的缩放是 1,所以 ψ0\psi_0、ψN\psi_N 不受这个因子影响。

Why can ψj\psi_j be compared with λ(xj)\lambda(x_j) directly, with the same sign and without a factor of the mesh width? The rows of Section 5 are integrals over the dual volumes: Rj=Hj−Hj−1−(Qj−Qj−1)R_j=H_j-H_{j-1}-(Q_j-Q_{j-1}) is the net numerical flux out of VjV_j minus the exact integral of the source over VjV_j, so Rj≈∫Vj(qx−s) dxR_j\approx\int_{V_j}(q_x-s)\,\mathrm dx, and wjUj≈∫Vj(1+x) u dxw_jU_j\approx\int_{V_j}(1+x)\,u\,\mathrm dx. Hence Jh+ψTR≈J+∫01λ (qx−s) dxJ_h+\psi^TR\approx J+\int_0^1\lambda\,(q_x-s)\,\mathrm dx when ψj≈λ(xj)\psi_j\approx\lambda(x_j), as in A.2. (The rows of Appendix B are divided by hh; there ψj≈h λ(xj)\psi_j\approx h\,\lambda(x_j): the scaling of ψ\psi follows the scaling of the rows.) The constraint rows have unit scaling, so ψ0\psi_0 and ψN\psi_N are not affected by this factor.

下表给出默认设计下的两部分(无限制器线性重构,本页的模型,N=8N=8 到 256),最后一行是 A.5 的连续值。

The table gives the two parts at the default design (unlimited linear reconstruction, this page's model, N=8N=8 to 256); the last row holds the continuous values of A.5.

NNψ0\psi_0ψN\psi_Naa:内部行之和aa: interior rowsaa:两个约束行aa: the two constraint rowsφ\varphi:内部行之和φ\varphi: interior rowsφ\varphi:两个约束行φ\varphi: the two constraint rows
8−1.40608−0.087010.45766−0.635732.11760−1.69770
16−1.40116−0.051580.48842−0.618551.81638−1.65182
32−1.41357−0.035210.47818−0.616861.74862−1.64732
64−1.42122−0.027360.47395−0.616781.73487−1.64710
128−1.42468−0.023910.47296−0.616781.73252−1.64711
256−1.42599−0.022610.47280−0.616781.73225−1.64711
连续continuous−1.42657−0.022030.47278−0.616781.73227−1.64712

读法与 A.5 相同。边界部分是两个乘子之和,−(ψ0+ψN) ∂ub/∂Dk-(\psi_0+\psi_N)\,\partial u_{\rm b}/\partial D_k(入口值与出口值的导数相同):N=8N=8 时它与连续的边界项相差 3.1%(两个分量都如此),ψ0\psi_0 单独与 νλx(0)=−1.4266\nu\lambda_x(0)=−1.4266 相差 1.4%,尽管第一个区间是层宽的 11.4 倍。内部行之和反而是不太准的一部分:φ\varphi 的那一项在 N=8N=8 时偏大 22%(2.1176 对 1.7323),又因为它与边界部分几乎抵消,所以 φ\varphi 梯度成了 0.4199,而不是 0.0852:错了它自身的 3.9 倍。加密之后两部分都趋于连续值(最后一行);表里没有阶,阶是第 15、16 节的话题。

Read it as in A.5. The boundary part is the sum of two multipliers, −(ψ0+ψN) ∂ub/∂Dk-(\psi_0+\psi_N)\,\partial u_{\rm b}/\partial D_k (the derivatives of the inlet and outlet values are equal): at N=8N=8 it is within 3.1% of the continuous boundary term, for both components, and ψ0\psi_0 alone is within 1.4% of νλx(0)=−1.4266\nu\lambda_x(0)=−1.4266, although the first interval is 11.4 times wider than the layer. The interior sum is the less accurate part: for φ\varphi it is 22% too large at N=8N=8 (2.1176 against 1.7323), and because it nearly cancels against the boundary part, the φ\varphi gradient comes out as 0.4199 instead of 0.0852: wrong by 3.9 times its own size. Under refinement both parts approach the continuous values (last row); the table says nothing about orders, which are the subject of Sections 15 and 16.

独立的稀疏实现(附录 C)把这张表继续到 N=16384N=16384:ψ0=−1.4265678\psi_0=−1.4265678、ψN=−0.0220347\psi_N=−0.0220347,与 νλx(0)\nu\lambda_x(0) 和 −νλx(1)-\nu\lambda_x(1) 相差 1.7e−7 与 1.7e−7;从 N=8192N=8192 到 N=16384N=16384,两个误差的观测阶是 2.00 与 2.00(数值证据,不是定理)。在共同的网格 N=32,…,256N=32,\dots,256 上,它与本页模型的 ψ0\psi_0、ψN\psi_N 相差不到 2e−14(三种重构,check_g.js)。

The independent sparse implementation (Appendix C) continues the table to N=16384N=16384: ψ0=−1.4265678\psi_0=−1.4265678 and ψN=−0.0220347\psi_N=−0.0220347, which differ from νλx(0)\nu\lambda_x(0) and −νλx(1)-\nu\lambda_x(1) by 1.7e−7 and 1.7e−7; between N=8192N=8192 and N=16384N=16384 the two errors have observed orders 2.00 and 2.00 (numerical evidence, not a theorem). On the common meshes N=32,…,256N=32,\dots,256 it agrees with the ψ0\psi_0, ψN\psi_N of this page's model to within 2e−14 (three reconstructions, check_g.js).

关于乘子有一个精确的结论:ATψ=−gA^T\psi=-g 的第 00 个方程(即 AA 的第 00 列)写作 A00ψ0+A10ψ1+A20ψ2=−w0A_{00}\psi_0+A_{10}\psi_1+A_{20}\psi_2=-w_0(约束行的对角元 A00=1A_{00}=1,第 1、2 行是仅有的另外两行含 U0U_0)。一阶重构时 A20=0A_{20}=0,A10=−(1+ν/h+U0/2)A_{10}=-(1+\nu/h+U_0/2),于是

One statement about the multiplier is exact: equation 00 of ATψ=−gA^T\psi=-g (column 00 of AA) reads A00ψ0+A10ψ1+A20ψ2=−w0A_{00}\psi_0+A_{10}\psi_1+A_{20}\psi_2=-w_0 (the constraint row has the diagonal A00=1A_{00}=1, and rows 1 and 2 are the only others that contain U0U_0). With first-order reconstruction A20=0A_{20}=0 and A10=−(1+ν/h+U0/2)A_{10}=-(1+\nu/h+U_0/2), so

ψ0=(1+νh+U02)ψ1−h2.\psi_0=\Bigl(1+\frac\nu h+\frac{U_0}2\Bigr)\psi_1-\frac h2 .

因子里的 ν/h\nu/h 是入口面上的黏性通量 ν(ψ1−0)/h\nu(\psi_1-0)/h(伴随在入口为零),U0/2U_0/2 是中心对流通量,11 是 Rusanov 耗散;网格没有分辨层时 ν/h\nu/h 很小,乘子主要由后两项决定。N=8N=8 时(一阶,默认设计):1.5374×(−0.8759)−0.0625=−1.40911.5374\times(−0.8759)-0.0625=−1.4091。二阶重构时同一个方程还多一项 A20ψ2A_{20}\psi_2,恒等式的形状不变。

In the factor, ν/h\nu/h is the viscous flux through the inlet face, ν(ψ1−0)/h\nu(\psi_1-0)/h (the adjoint vanishes at the inlet), U0/2U_0/2 is the central convective flux and 11 the Rusanov dissipation; when the mesh does not resolve the layer, ν/h\nu/h is small and the other two terms carry the multiplier. At N=8N=8 (first order, default design): 1.5374×(−0.8759)−0.0625=−1.40911.5374\times(−0.8759)-0.0625=−1.4091. With second-order reconstruction the same equation has one more term A20ψ2A_{20}\psi_2; the shape of the identity is unchanged.

图 108 · 本页网格上的离散伴随(默认设计,无限制器线性)。(a)(b) 内部节点上的 ψ_j(N=8:方块,32:圈,128:点)与 λ(x)(线);j=0 与 j=N 的乘子不是 λ 的值,没有画;竖虚线是层宽 ν/u_in。(c) 梯度里入口数据的伴随 u-bar_in:本页是 -ψ_0(点),格心页是它自己的 u-bar_in(方块,那一页的模型,同一设计),虚线是连续值 -νλ_x(0),点线是 -u_inλ_out(0);两种格式的入口项在粗网格上就接近连续值。(d) 两个边界项与连续值之差:入口是 |u-bar_in+νλ_x(0)|,出口是 |u-bar_out-νλ_x(1)|(对数坐标;N>256 的点是独立稀疏实现的存储数据,见;点线是 h^2 参考):本页的出口项 -ψ_N 与格心页的 u-bar_out 都很小,相对误差在粗网格上很大。−1.5−1−0.5000.20.40.60.81xψj​ 与 λ(a) 内部节点:ψj​(点)与 λ(线)N = 8N = 32N = 128−1.5−1−0.5000.020.040.060.080.10.120.14x(b) 入口附近放大ν/uin​1.351.41.451.510100N(c) 入口项 ūin​本页:−ψ0​格心页:ūin​−νλx​(0)−uin​λout​(0)10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​10102​103​104​N(d) 两个边界项的误差本页:入口本页:出口格心页:入口格心页:出口h²
图 108 · 本页网格上的离散伴随(默认设计,无限制器线性)。(a)(b) 内部节点上的 ψj\psi_j(N=8N=8:方块,32:圈,128:点)与 λ(x)\lambda(x)(线);j=0j=0 与 j=Nj=N 的乘子不是 λ\lambda 的值,没有画;竖虚线是层宽 ν/uin\nu/u_{\rm in}。(c) 梯度里入口数据的伴随 uˉin\bar u_{\rm in}:本页是 −ψ0-\psi_0(点),格心页是它自己的 uˉin\bar u_{\rm in}(方块,那一页的模型,同一设计),虚线是连续值 −νλx(0)-\nu\lambda_x(0),点线是 −uinλout(0)-u_{\rm in}\lambda_{\rm out}(0);两种格式的入口项在粗网格上就接近连续值。(d) 两个边界项与连续值之差:入口是 ∣uˉin+νλx(0)∣|\bar u_{\rm in}+\nu\lambda_x(0)|,出口是 ∣uˉout−νλx(1)∣|\bar u_{\rm out}-\nu\lambda_x(1)|(对数坐标;N>256N>256 的点是独立稀疏实现的存储数据,见附录 C;点线是 h2h^2 参考):本页的出口项 −ψN-\psi_N 与格心页的 uˉout\bar u_{\rm out} 都很小,相对误差在粗网格上很大。
Figure 108 · The discrete adjoint on this page's mesh (default design, unlimited linear). (a)(b) ψ_j at the interior nodes (N=8: squares, 32: rings, 128: dots) and λ(x) (line); the multipliers of j=0 and j=N are not values of λ and are not drawn; the vertical dashes mark the layer width ν/u_in. (c) The adjoint u-bar_in of the inlet datum in the gradient: on this page -ψ_0 (dots), on the cell-centred page its own u-bar_in (squares; the model of that page, same design); dashed, the continuous value -νλ_x(0), dotted -u_inλ_out(0). Both schemes are close to the continuous value on coarse meshes. (d) The errors of the two boundary terms against the continuous values, inlet |u-bar_in+νλ_x(0)| and outlet |u-bar_out-νλ_x(1)| (log axes; the points beyond N=256 are the stored runs of the independent sparse implementation, ; dotted, an h^2 reference): the outlet terms -ψ_N and u-bar_out are small, and their relative errors are large on coarse meshes.−1.5−1−0.5000.20.40.60.81xψj​ and λ(a) interior nodes: ψj​ (dots) and λ (line)N = 8N = 32N = 128−1.5−1−0.5000.020.040.060.080.10.120.14x(b) zoom near the inletν/uin​1.351.41.451.510100N(c) the inlet term ūin​this page: −ψ0​cell page: ūin​−νλx​(0)−uin​λout​(0)10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​10102​103​104​N(d) errors of the two boundary termsthis page: inletthis page: outletcell page: inletcell page: outleth²
Figure 108 · The discrete adjoint on this page's mesh (default design, unlimited linear). (a)(b) ψj\psi_j at the interior nodes (N=8N=8: squares, 32: rings, 128: dots) and λ(x)\lambda(x) (line); the multipliers of j=0j=0 and j=Nj=N are not values of λ\lambda and are not drawn; the vertical dashes mark the layer width ν/uin\nu/u_{\rm in}. (c) The adjoint uˉin\bar u_{\rm in} of the inlet datum in the gradient: on this page −ψ0-\psi_0 (dots), on the cell-centred page its own uˉin\bar u_{\rm in} (squares; the model of that page, same design); dashed, the continuous value −νλx(0)-\nu\lambda_x(0), dotted −uinλout(0)-u_{\rm in}\lambda_{\rm out}(0). Both schemes are close to the continuous value on coarse meshes. (d) The errors of the two boundary terms against the continuous values, inlet ∣uˉin+νλx(0)∣|\bar u_{\rm in}+\nu\lambda_x(0)| and outlet ∣uˉout−νλx(1)∣|\bar u_{\rm out}-\nu\lambda_x(1)| (log axes; the points beyond N=256N=256 are the stored runs of the independent sparse implementation, Appendix C; dotted, an h2h^2 reference): the outlet terms −ψN-\psi_N and uˉout\bar u_{\rm out} are small, and their relative errors are large on coarse meshes.

自己试:选 NN 与重构,实验台在浏览器里重新解本页的格点格式,画出 ψj\psi_j 与 λ\lambda,给出两个乘子、梯度的两部分和格心页的对应值(只有默认设计有)。

Try it: choose NN and the reconstruction; the lab solves this page's node scheme again in the browser, draws ψj\psi_j against λ\lambda, and reports the two multipliers, the two parts of the gradient and the cell-centred page's counterparts (available at the default design only).

附录 B:Dirichlet–Neumann 格点基准

Appendix B: A Dirichlet–Neumann nodal benchmark

本节实验:这是另一个模型,未知量同样放在节点上,但行除以 hh,x=1x=1 处是 Neumann 条件。离散伴随 ψj/h\psi_j/h 在每个节点上都逼近连续伴随吗?先预测最后一个 PDE 节点上的比值 ψN−1/(hλ(xN−1))\psi_{N-1}/(h\lambda(x_{N-1})),再看图 111。

Experiment: a different model, with the unknowns at the nodes as on this page but the rows divided by hh and a Neumann condition at x=1x=1. Does the discrete adjoint ψj/h\psi_j/h approach the continuous adjoint at every node? Predict the ratio ψN−1/(hλ(xN−1))\psi_{N-1}/(h\lambda(x_{N-1})) at the last PDE node first, then read Figure 111.

本附录讲的是另一个模型:它是为一篇论文建立的(Python 包的 paper_dn/ 文件夹,见附录 C)。它的网格与本页相同——未知量是节点值 uju_j,控制体是对偶区间——代码也还是五条语句(取值、通量、分发、源项、覆盖)。不同的是:面通量是没有 Rusanov 耗散的中心通量(也不重构),每一行除以 hh(是密度,不是对偶控制体上的积分),源项在节点上采样(第 5 节用精确积分),出口是 Neumann 条件(一个单侧二阶差分;本页的出口是第二个 Dirichlet 约束),设计变量只有一个 μ\mu,目标里的权重是冻结的。为了不和正文的模型混淆,它用自己的字母:状态 uju_j、设计 μ\mu(不是 DD)、权重 ω\omega;这些字母和 B.7 的 ρ\rho、η\eta、gg、ghg_h 只在本附录里有效(第 4、6、7、16、17、18 节的 ω\omega、μ\mu、ρ\rho 另有含义),掩码 QQ 不是第 5 节的精确通量 QfQ_f,这里的 ψ0\psi_0、ψN\psi_N 同样是两个替换行的乘子,只是行的缩放不同(B.4)。下面的结论不适用于正文的模型,反过来也一样。

This appendix is about a different model, built for a paper (the folder paper_dn/ of the Python package, see Appendix C). Its mesh is that of this page, with the unknowns at the nodes xjx_j as nodal values uju_j and the dual intervals as control volumes, and its code is again five statements (gather, flux, scatter, source, overwrite). What differs: the face flux is the central flux without Rusanov dissipation (and without reconstruction), every row is divided by hh (a density, not an integral over a dual volume), the source is sampled at the node (where Section 5 integrates it exactly), the outlet carries a Neumann condition (a one-sided second-order difference; the outlet of this page is a second Dirichlet constraint), there is a single design parameter μ\mu, and the weight of the objective is frozen. To keep it apart from the main model it has its own letters: state uju_j, design μ\mu (not DD), weight ω\omega; these, and ρ\rho, η\eta, gg, ghg_h of B.7, hold only in this appendix (Sections 4, 6, 7, 16, 17 and 18 use ω\omega, μ\mu, ρ\rho for other things), the mask QQ is not the exact flux QfQ_f of Section 5, and ψ0\psi_0, ψN\psi_N here are again the multipliers of the two replaced rows, with a different scaling of the rows (B.4). Nothing below transfers to the main model, nor the other way round.

为什么放在这里:它的精确解、源项、权重和主基准的伴随都是有理系数多项式,可以精确核对;它有两个被边界条件替换的行(一个 Dirichlet、一个 Neumann),正好用正文的自动微分记号写一遍,与第 4 节的约束行对照;它说明行的缩放怎样决定 ψ\psi 的缩放(这里 ψj≈h λ(xj)\psi_j\approx h\,\lambda(x_j),第 16 节里 ψj≈λ(xj)\psi_j\approx\lambda(x_j));还有一份理论审阅给出证明和误差界,本附录逐条核对。

Why it is here: its exact state, source, weight and primary adjoint are polynomials with rational coefficients and can be checked exactly; it has two rows replaced by boundary conditions (a Dirichlet and a Neumann one), which this appendix writes in the automatic-differentiation notation of the main text, to be compared with the constraint rows of Section 4; it shows how the scaling of the rows sets the scaling of ψ\psi (here ψj≈h λ(xj)\psi_j\approx h\,\lambda(x_j), in Section 16 ψj≈λ(xj)\psi_j\approx\lambda(x_j)); and a theory review supplies proofs and error bounds, which this appendix audits one by one.

B.1 模型与精确解

B.1 The model and its exact solution

−νuxx+(12u2)x=s(x;μ),u(0)=1,ux(1)=0,uμ∗=1+μx(2−x),s=2μ(1−x) uμ∗+2νμ.-\nu u_{xx}+\bigl(\tfrac12u^2\bigr)_x=s(x;\mu),\qquad u(0)=1,\quad u_x(1)=0,\qquad u^*_\mu=1+\mu x(2-x),\qquad s=2\mu(1-x)\,u^*_\mu+2\nu\mu .

uμ∗u^*_\mu 对每个 μ\mu 都满足方程和两个边界条件(uμ,x∗=2μ(1−x)u^*_{\mu,x}=2\mu(1-x) 在 x=1x=1 为零)。黏性固定:主基准 ν=0.1\nu=0.1,次基准 ν=0.05\nu=0.05;设计的基点 μ0=0.2\mu_0=0.2。精确的切线解 v∗=∂uμ∗/∂μ=x(2−x)v^*=\partial u^*_\mu/\partial\mu=x(2-x) 与 μ\mu 无关。

uμ∗u^*_\mu satisfies the equation and both boundary conditions for every μ\mu (uμ,x∗=2μ(1−x)u^*_{\mu,x}=2\mu(1-x) vanishes at x=1x=1). The viscosity is fixed: ν=0.1\nu=0.1 for the primary case, ν=0.05\nu=0.05 for the secondary; the base design is μ0=0.2\mu_0=0.2. The exact tangent v∗=∂uμ∗/∂μ=x(2−x)v^*=\partial u^*_\mu/\partial\mu=x(2-x) does not depend on μ\mu.

目标是 J(u)=∫01ω u dxJ(u)=\int_0^1\omega\,u\,\mathrm dx,权重 ω\omega 在 μ0\mu_0 处构造一次,之后冻结:μ\mu 改变时它不变。主基准的权重是“先给伴随,再算权重”(构造的伴随):取 λ∗(x)=−x(1−ϑx)\lambda^*(x)=-x(1-\vartheta x),ϑ=(ν+1+μ0)/(2ν+1+μ0)=1314\vartheta=(\nu+1+\mu_0)/(2\nu+1+\mu_0)=\frac{13}{14}(ϑ\vartheta 使 λ∗\lambda^* 满足 B.2 的出口条件),令 ω:=uμ0∗λx∗+νλxx∗\omega:=u^*_{\mu_0}\lambda^*_x+\nu\lambda^*_{xx},于是 λ∗\lambda^* 恰好是 μ0\mu_0 处的伴随。用有理数精确计算:

The objective is J(u)=∫01ω u dxJ(u)=\int_0^1\omega\,u\,\mathrm dx with a weight ω\omega built once at μ0\mu_0 and then frozen: it does not change when μ\mu does. The primary weight is made by choosing the adjoint first (a manufactured adjoint): take λ∗(x)=−x(1−ϑx)\lambda^*(x)=-x(1-\vartheta x) with ϑ=(ν+1+μ0)/(2ν+1+μ0)=1314\vartheta=(\nu+1+\mu_0)/(2\nu+1+\mu_0)=\frac{13}{14} (ϑ\vartheta makes λ∗\lambda^* satisfy the outlet condition of B.2) and set ω:=uμ0∗λx∗+νλxx∗\omega:=u^*_{\mu_0}\lambda^*_x+\nu\lambda^*_{xx}, so that λ∗\lambda^* is exactly the adjoint at μ0\mu_0. In exact rational arithmetic:

ω(x)=−5770+5135x+3335x2−1335x3,J(μ)=∫01ω uμ∗ dx=19140+5472100 μ,dJdμ=5472100.\omega(x)=-\tfrac{57}{70}+\tfrac{51}{35}x+\tfrac{33}{35}x^2-\tfrac{13}{35}x^3,\qquad J(\mu)=\int_0^1\omega\,u^*_\mu\,\mathrm dx=\frac{19}{140}+\frac{547}{2100}\,\mu,\qquad \frac{\mathrm dJ}{\mathrm d\mu}=\frac{547}{2100}.

论文和数据把这个权重叫 q0q_0(目标名“q0”);本页的 qq 是通量,所以写作 ω\omega。JJ 对 μ\mu 是线性的,精确梯度 5472100\frac{547}{2100} 对每个 μ\mu 都成立;但 λ∗\lambda^* 只在 μ=μ0\mu=\mu_0 处是伴随。次基准用正文的权重 ω=1+x\omega=1+x,ν=0.05\nu=0.05:J=32+1312μJ=\tfrac32+\frac{13}{12}\mu,梯度 1312\frac{13}{12}。

The paper and the data call this weight q0q_0 (objective “q0”); on this page qq is the flux, hence ω\omega. JJ is linear in μ\mu, so the exact gradient 5472100\frac{547}{2100} holds for every μ\mu, but λ∗\lambda^* is the adjoint only at μ=μ0\mu=\mu_0. The secondary case uses the main text's weight ω=1+x\omega=1+x with ν=0.05\nu=0.05: J=32+1312μJ=\tfrac32+\frac{13}{12}\mu, gradient 1312\frac{13}{12}.

图 109 · 基准的组成部分。(a) 精确解族 u*_μ:在 x=1 处斜率为零(Neumann)。(b) μ_0=0.2 处的源项,两种黏性系数。(c) 冻结的权重:主基准的三次多项式 ω(论文的 q_0)与次基准的 1+x。(d) 本页正负号约定下的连续伴随:主基准是解析的 λ*=-x(1- x),次基准由配点法求得;两者都在 x=0 为零,在 x=1 满足 Robin 条件。11.11.21.31.41.500.20.40.60.81xu*μ​(a) 精确解 1 + μx(2 − x),ux​(1) = 0μ = 0μ = 0.1μ = 0.2μ = 0.3μ = 0.500.10.20.30.400.20.40.60.81xs(b) 源项 s(x; μ = 0.2)ν = 0.1ν = 0.05−1−0.500.511.5200.20.40.60.81xω(c) 冻结的目标权重主基准 ω(论文的 q0​)次基准 ω = 1 + x−1.2−1−0.8−0.6−0.4−0.2000.20.40.60.81xλ(d) 连续伴随(本页的正负号约定)主基准 λ* = −x(1 − ϑx)次基准(配点法)
图 109 · 基准的组成部分。(a) 精确解族 uμ∗u^*_\mu:在 x=1x=1 处斜率为零(Neumann)。(b) μ0=0.2\mu_0=0.2 处的源项,两种黏性系数。(c) 冻结的权重:主基准的三次多项式 ω\omega(论文的 q0q_0)与次基准的 1+x1+x。(d) 本页正负号约定下的连续伴随:主基准是解析的 λ∗=−x(1−ϑx)\lambda^*=-x(1-\vartheta x),次基准由配点法求得;两者都在 x=0x=0 为零,在 x=1x=1 满足 Robin 条件。
Figure 109 · The parts of the benchmark. (a) The family of exact states u*_μ, flat at x=1 (Neumann). (b) The source at μ_0=0.2 for the two viscosities. (c) The frozen weights: the cubic ω of the primary case (the paper's q_0) and 1+x of the secondary. (d) The continuous adjoints in the page's sign: the analytic λ*=-x(1- x) of the primary case and the collocation solution of the secondary; both vanish at x=0 and satisfy the Robin condition at x=1.11.11.21.31.41.500.20.40.60.81xu*μ​(a) exact state 1 + μx(2 − x), ux​(1) = 0μ = 0μ = 0.1μ = 0.2μ = 0.3μ = 0.500.10.20.30.400.20.40.60.81xs(b) source s(x; μ = 0.2)ν = 0.1ν = 0.05−1−0.500.511.5200.20.40.60.81xω(c) the frozen weightsprimary ω (the paper’s q0​)secondary ω = 1 + x−1.2−1−0.8−0.6−0.4−0.2000.20.40.60.81xλ(d) continuous adjoints (page sign)primary λ* = −x(1 − ϑx)secondary (collocation)
Figure 109 · The parts of the benchmark. (a) The family of exact states uμ∗u^*_\mu, flat at x=1x=1 (Neumann). (b) The source at μ0=0.2\mu_0=0.2 for the two viscosities. (c) The frozen weights: the cubic ω\omega of the primary case (the paper's q0q_0) and 1+x1+x of the secondary. (d) The continuous adjoints in the page's sign: the analytic λ∗=−x(1−ϑx)\lambda^*=-x(1-\vartheta x) of the primary case and the collocation solution of the secondary; both vanish at x=0x=0 and satisfy the Robin condition at x=1x=1.

B.2 Neumann 端的连续伴随

B.2 The continuous adjoint at a Neumann end

拉格朗日函数与附录 A 相同:ℒ=J+∫01λ(qx−s) dx\mathcal L=J+\int_0^1\lambda(q_x-s)\,\mathrm dx。切线解 v=∂u/∂μv=\partial u/\partial\mu 满足 (uv−νvx)x=sμ(uv-\nu v_x)_x=s_\mu,v(0)=0v(0)=0(入口值 1 与 μ\mu 无关),vx(1)=0v_x(1)=0。附录 A 的两次分部积分给出

The Lagrangian is that of Appendix A: ℒ=J+∫01λ(qx−s) dx\mathcal L=J+\int_0^1\lambda(q_x-s)\,\mathrm dx. The tangent v=∂u/∂μv=\partial u/\partial\mu satisfies (uv−νvx)x=sμ(uv-\nu v_x)_x=s_\mu with v(0)=0v(0)=0 (the inlet value 1 does not depend on μ\mu) and vx(1)=0v_x(1)=0. The two integrations by parts of Appendix A give

∫01λ (uv−νvx)x dx=∫01(−uλx−νλxx) v dx+[λuv−νλvx+νλxv]01.\int_0^1\lambda\,(uv-\nu v_x)_x\,\mathrm dx=\int_0^1\bigl(-u\lambda_x-\nu\lambda_{xx}\bigr)\,v\,\mathrm dx+\bigl[\lambda uv-\nu\lambda v_x+\nu\lambda_xv\bigr]_0^1 .

代入 v(0)=0v(0)=0、vx(1)=0v_x(1)=0,端点项只剩 νλ(0) vx(0)+[u(1)λ(1)+νλx(1)]v(1)\nu\lambda(0)\,v_x(0)+\bigl[u(1)\lambda(1)+\nu\lambda_x(1)\bigr]v(1)。vx(0)v_x(0) 和 v(1)v(1) 都未知,所以两个系数都必须为零:

With v(0)=0v(0)=0 and vx(1)=0v_x(1)=0 the end terms reduce to νλ(0) vx(0)+[u(1)λ(1)+νλx(1)]v(1)\nu\lambda(0)\,v_x(0)+\bigl[u(1)\lambda(1)+\nu\lambda_x(1)\bigr]v(1). Both vx(0)v_x(0) and v(1)v(1) are unknown, so both coefficients must vanish:

−uλx−νλxx=−ω,λ(0)=0,νλx(1)+u(1)λ(1)=0,dJdμ=−∫01λ sμ dx.-u\lambda_x-\nu\lambda_{xx}=-\omega,\qquad \lambda(0)=0,\qquad \nu\lambda_x(1)+u(1)\lambda(1)=0,\qquad \frac{\mathrm dJ}{\mathrm d\mu}=-\int_0^1\lambda\,s_\mu\,\mathrm dx .

对照附录 A:Dirichlet 端给 λ=0\lambda=0,Neumann 端给 λ\lambda 的 Robin 条件。梯度里没有边界项,因为边界数据不依赖 μ\mu。精确核对:λ∗\lambda^* 在 μ0\mu_0 处满足这三个条件,−∫01λ∗sμ dx=5472100-\int_0^1\lambda^*s_\mu\,\mathrm dx=\frac{547}{2100}(check_dn.py 用 sympy 逐项验证)。

Compare with Appendix A: a Dirichlet end gives λ=0\lambda=0, a Neumann end a Robin condition for λ\lambda. There is no boundary term in the gradient because the boundary data do not depend on μ\mu. Exact check: λ∗\lambda^* satisfies the three conditions at μ0\mu_0 and −∫01λ∗sμ dx=5472100-\int_0^1\lambda^*s_\mu\,\mathrm dx=\frac{547}{2100} (verified term by term with sympy by check_dn.py).

边界条件的乘子。若把 u(0)=uinu(0)=u_{\rm in} 与 ux(1)=0u_x(1)=0 也作为约束,即在 ℒ\mathcal L 中加上 β0(u(0)−uin)+βNux(1)\beta_0\bigl(u(0)-u_{\rm in}\bigr)+\beta_Nu_x(1)(乘子 β0\beta_0、βN\beta_N),那么 v(0)v(0)、vx(1)v_x(1) 都是自由的,它们的系数给出 β0=νλx(0)\beta_0=\nu\lambda_x(0)、βN=νλ(1)\beta_N=\nu\lambda(1),并且 dJ/duin=−β0=−νλx(0)\mathrm dJ/\mathrm du_{\rm in}=-\beta_0=-\nu\lambda_x(0)——与附录 A 的边界项相同。B.4 里两个被替换行的乘子逼近的就是它们。

Multipliers of the boundary conditions. If u(0)=uinu(0)=u_{\rm in} and ux(1)=0u_x(1)=0 are also added to ℒ\mathcal L as constraints, i.e. β0(u(0)−uin)+βNux(1)\beta_0\bigl(u(0)-u_{\rm in}\bigr)+\beta_Nu_x(1) is added to ℒ\mathcal L (multipliers β0\beta_0, βN\beta_N), then v(0)v(0) and vx(1)v_x(1) are free, and their coefficients give β0=νλx(0)\beta_0=\nu\lambda_x(0) and βN=νλ(1)\beta_N=\nu\lambda(1), with dJ/duin=−β0=−νλx(0)\mathrm dJ/\mathrm du_{\rm in}=-\beta_0=-\nu\lambda_x(0): the boundary term of Appendix A again. These are what the multipliers of the two replaced rows approximate in B.4.

正负号约定。理论审阅(THEORY_REVIEW.md)用 J−∫λRJ-\int\lambda R(“物理”伴随):它的 λ\lambda 满足 −uλx−νλxx=+ω-u\lambda_x-\nu\lambda_{xx}=+\omega,等于本页的 −λ-\lambda,梯度写成 +∫λsμ+\int\lambda s_\mu;它的 λ∗=x(1−ϑx)\lambda_*=x(1-\vartheta x)(审阅把 ϑ\vartheta 记作 c0c_0,把本页的 ww、ω\omega 记作 jj、ww;审阅在 J+ψTRJ+\psi^TR 约定下的连续密度 η\eta 就是本页的 λ\lambda)就是本页的 −λ∗-\lambda^*,离散密度 −ψj/h-\psi_j/h 就是本页的 ψj/h\psi_j/h 反号。两种约定给出同一个梯度,只是 λ\lambda 的符号相反。本页沿用正文的 Jh+ψTRJ_h+\psi^TR 与 J+∫λRJ+\int\lambda R,所以 ψ\psi 与 λ\lambda 同号。

The sign convention. The theory review (THEORY_REVIEW.md) uses J−∫λRJ-\int\lambda R (a “physical” adjoint): its λ\lambda solves −uλx−νλxx=+ω-u\lambda_x-\nu\lambda_{xx}=+\omega and equals −λ-\lambda of this page, with the gradient written +∫λsμ+\int\lambda s_\mu; its λ∗=x(1−ϑx)\lambda_*=x(1-\vartheta x) (the review writes c0c_0 for ϑ\vartheta, and jj, ww for this page's ww, ω\omega; its continuous density η\eta of the J+ψTRJ+\psi^TR convention is this page's λ\lambda) is this page's −λ∗-\lambda^*, and its discrete density −ψj/h-\psi_j/h is this page's ψj/h\psi_j/h with the sign flipped. Both conventions give the same gradient; only the sign of λ\lambda differs. This page keeps the main text's Jh+ψTRJ_h+\psi^TR and J+∫λRJ+\int\lambda R, so ψ\psi and λ\lambda have the same sign.

B.3 格式:节点、中心通量、两个替换行

B.3 The scheme: nodes, central fluxes, two replaced rows

节点 xj=jhx_j=jh,j=0,…,Nj=0,\dots,N,h=1/Nh=1/N(NN 是区间数,与第 2 节相同);未知量 u0,…,uNu_0,\dots,u_N 是节点值。相邻节点之间是面 xj+1/2x_{j+1/2},面上的中心通量

Nodes xj=jhx_j=jh, j=0,…,Nj=0,\dots,N, h=1/Nh=1/N (NN counts intervals, as in Section 2); the unknowns u0,…,uNu_0,\dots,u_N are nodal values. Between two nodes sits the face xj+1/2x_{j+1/2} with the central flux

Hj+1/2=14(uj2+uj+12)−κ (uj+1−uj),κ=ν/h,H_{j+1/2}=\tfrac14\bigl(u_j^2+u_{j+1}^2\bigr)-\kappa\,(u_{j+1}-u_j),\qquad \kappa=\nu/h,

就是第 3 节的 HfH_f 取 α=0\alpha=0(没有 Rusanov 耗散,即没有 HfH_f 里的 −(qR−qL)-(q_R-q_L) 项)、不重构(qL=ujq_L=u_j,qR=uj+1q_R=u_{j+1})、df=hd_f=h。内部节点的行除以 hh(密度;第 5 节的行是对偶控制体上的积分),源项在节点上采样(第 5 节用精确积分):

which is the face flux HfH_f of Section 3 with α=0\alpha=0 (no Rusanov dissipation, that is, without the term −(qR−qL)-(q_R-q_L) of HfH_f), no reconstruction (qL=ujq_L=u_j, qR=uj+1q_R=u_{j+1}) and df=hd_f=h. The rows of the interior nodes are divided by hh (densities; the rows of Section 5 are integrals over the dual volumes), with the source sampled at the node (Section 5 integrates it exactly):

Rj=Hj+1/2−Hj−1/2h−s(xj;μ)=uj+12−uj−124h−ν uj+1−2uj+uj−1h2−s(xj;μ),1≤j≤N−1.R_j=\frac{H_{j+1/2}-H_{j-1/2}}{h}-s(x_j;\mu)=\frac{u_{j+1}^2-u_{j-1}^2}{4h}-\nu\,\frac{u_{j+1}-2u_j+u_{j-1}}{h^2}-s(x_j;\mu),\qquad 1\le j\le N-1 .

两端的行被边界条件替换:R0=u0−1R_0=u_0-1(Dirichlet:第 4 节的约束行,uin=1u_{\rm in}=1),RN=(3uN−4uN−1+uN−2)/(2h)R_N=(3u_N-4u_{N-1}+u_{N-2})/(2h)(ux(1)=0u_x(1)=0 的二阶单侧差分;本页在这里放的是 UN−uoutU_N-u_{\rm out})。目标用梯形公式 Jh=∑jwjujJ_h=\sum_jw_ju_j,wj=h ω(xj)w_j=h\,\omega(x_j),j=0j=0 与 j=Nj=N 处减半。Python 程序(benchmark.py)消去 u0=1u_0=1,只保留 u1,…,uNu_1,\dots,u_N:方程相同,ψ1,…,ψN\psi_1,\dots,\psi_N 也相同(B.4);这里保留 u0u_0,让两个替换行写法一致。

The two end rows are replaced by the boundary conditions: R0=u0−1R_0=u_0-1 (Dirichlet: the constraint row of Section 4 with uin=1u_{\rm in}=1) and RN=(3uN−4uN−1+uN−2)/(2h)R_N=(3u_N-4u_{N-1}+u_{N-2})/(2h) (the one-sided, second-order ux(1)=0u_x(1)=0; where this page puts UN−uoutU_N-u_{\rm out}). The objective is the trapezoid rule Jh=∑jwjujJ_h=\sum_jw_ju_j with wj=h ω(xj)w_j=h\,\omega(x_j), halved at j=0j=0 and j=Nj=N. The Python code (benchmark.py) eliminates u0=1u_0=1 and keeps only u1,…,uNu_1,\dots,u_N: the same equations and the same ψ1,…,ψN\psi_1,\dots,\psi_N (B.4); here u0u_0 is kept so that the two replaced rows read alike.

图 110 · 格点格式的三种行与 N=8 的 Jacobian(主基准的收敛解)。内部行读三个节点、两个面通量;第 0 行与第 N 行被边界条件替换(橙黄色)。热图里蓝正橙负;紫框是两个替换行。注意元素的量级:行是密度,所以内部行的对角元是 2ν/h^2。节点 xj​ = j h(N = 8)、半节点面 xj+½​,以及三种行u0​u1​u2​u3​u4​u5​u6​u7​u8​内部行 R4​:两个面通量之差 / h − s(x4​)H3½​H4½​R0​ = u0​ − 1(Dirichlet,替换行)1−43R8​ = (3u8​ − 4u7​ + u6​)/(2h)(Neumann ux​(1) = 0,替换行)1.0−10.412.8−2.0−10.612.8−1.9−10.812.8−1.8−10.912.8−1.7−11.012.8−1.6−11.112.8−1.6−11.212.8−1.64.0−16.012.0012345678012345678A = Ru​(N = 8,收敛解)第 0 行与第 8 行(紫框)被边界条件替换:第 0 行只有对角元 1;第 8 行是 (1, −4, 3)/(2h) = (4, −16, 12)。内部行:对角 2ν/h² = 12.8,两侧 −ν/h² ∓ u/(2h)。每行都除以 h(密度),所以元素是 O(1/h²);正文的行是对偶控制体上的积分(元素 O(1/h))。第 8 行的 −4 紧挨对角线,1 在左边第二格:A 的下带宽是 2,本页的带状 LU与它的转置照此处理。
图 110 · 格点格式的三种行与 N=8N=8 的 Jacobian(主基准的收敛解)。内部行读三个节点、两个面通量;第 0 行与第 NN 行被边界条件替换(橙黄色)。热图里蓝正橙负;紫框是两个替换行。注意元素的量级:行是密度,所以内部行的对角元是 2ν/h22\nu/h^2。
Figure 110 · The three kinds of row of the nodal scheme and the Jacobian for N=8 (converged primary state). An interior row reads three nodes and two face fluxes; rows 0 and N are replaced by the boundary conditions (amber). In the heat map blue is positive and orange negative; the violet frames are the two replaced rows. Mind the size of the entries: the rows are densities, so the diagonal of an interior row is 2ν/h^2.nodes xj​ = j h (N = 8), half-node faces xj+½​, and the three kinds of rowu0​u1​u2​u3​u4​u5​u6​u7​u8​interior row R4​: difference of two face fluxes / h − s(x4​)H3½​H4½​R0​ = u0​ − 1(Dirichlet, replaced)1−43R8​ = (3u8​ − 4u7​ + u6​)/(2h)(Neumann ux​(1) = 0, replaced)1.0−10.412.8−2.0−10.612.8−1.9−10.812.8−1.8−10.912.8−1.7−11.012.8−1.6−11.112.8−1.6−11.212.8−1.64.0−16.012.0012345678012345678A = Ru​ (N = 8, converged state)rows 0 and 8 (violet frames) are replacedby the boundary conditions:row 0 holds only the diagonal 1;row 8 is (1, −4, 3)/(2h) = (4, −16, 12).interior rows: diagonal 2ν/h² = 12.8,neighbours −ν/h² ∓ u/(2h).every row is divided by h (a density), sothe entries are O(1/h²); the rows of the maintext are integrals over the dual volumes(entries O(1/h)).the −4 of row 8 sits next to the diagonaland the 1 two places left: the lowerbandwidth of A is 2; the banded LU handles it.
Figure 110 · The three kinds of row of the nodal scheme and the Jacobian for N=8N=8 (converged primary state). An interior row reads three nodes and two face fluxes; rows 00 and NN are replaced by the boundary conditions (amber). In the heat map blue is positive and orange negative; the violet frames are the two replaced rows. Mind the size of the entries: the rows are densities, so the diagonal of an interior row is 2ν/h22\nu/h^2.

写成程序是五条语句(一个面的取值、通量、分发,源项,以及覆盖),形状与第 5 节的残差代码相同,只是没有重构,它的前向与伴随代码就是第 8、9 节的写法;覆盖的写法与其他一维格点页相同——Q=diag(0,1,…,1,0)Q=\mathrm{diag}(0,1,\dots,1,0) 屏蔽两个替换行,b0=u0−uinb_0=u_0-u_{\rm in}、bN=(3uN−4uN−1+uN−2)/(2h)b_N=(3u_N-4u_{N-1}+u_{N-2})/(2h) 是两个约束,cL=uL/2c_L=u_L/2、cR=uR/2c_R=u_R/2 是通量对两侧状态的对流偏导(没有 Rusanov 耗散,所以没有第 3 节的 cLc_L、cRc_R 里的 ±1\pm1):

As code it is five statements (the gather, flux and scatter of one face, the source, and the overwrite), the shape of the residual code of Section 5 without reconstruction, with the tangent and reverse versions of Sections 8 and 9; the overwrite is written as on the node-centred pages of the other 1-D lessons: Q=diag(0,1,…,1,0)Q=\mathrm{diag}(0,1,\dots,1,0) masks the two replaced rows, b0=u0−uinb_0=u_0-u_{\rm in} and bN=(3uN−4uN−1+uN−2)/(2h)b_N=(3u_N-4u_{N-1}+u_{N-2})/(2h) are the two constraints, and cL=uL/2c_L=u_L/2, cR=uR/2c_R=u_R/2 are the convective partial derivatives of the flux (without Rusanov dissipation, hence without the ±1\pm1 of cLc_L, cRc_R in Section 3) with respect to the two states:

原始语句Primal statement前向(tangent)Tangent伴随(逆序执行)Adjoint (run in reverse order)
(1)uL=uj, uR=uj+1u_L=u_j,\ u_R=u_{j+1}u˙L=u˙j, u˙R=u˙j+1\dot u_L=\dot u_j,\ \dot u_R=\dot u_{j+1}uˉj+=uˉL, uˉj+1+=uˉR\bar u_j\mathrel{\text{+=}}\bar u_L,\ \bar u_{j+1}\mathrel{\text{+=}}\bar u_R
(2)H=14(uL2+uR2)−κ(uR−uL)H=\tfrac14(u_L^2+u_R^2)-\kappa(u_R-u_L)H˙=cLu˙L+cRu˙R+κ(u˙L−u˙R)\dot H=c_L\dot u_L+c_R\dot u_R+\kappa(\dot u_L-\dot u_R)uˉL=(cL+κ)Hˉ, uˉR=(cR−κ)Hˉ\bar u_L=(c_L+\kappa)\bar H,\ \bar u_R=(c_R-\kappa)\bar H
(3)Rraw,j+=H/h, Rraw,j+1-=H/hR_{{\rm raw},j}\mathrel{\text{+=}}H/h,\ R_{{\rm raw},j+1}\mathrel{\text{-=}}H/hR˙raw,j+=H˙/h, R˙raw,j+1-=H˙/h\dot R_{{\rm raw},j}\mathrel{\text{+=}}\dot H/h,\ \dot R_{{\rm raw},j+1}\mathrel{\text{-=}}\dot H/hHˉ=(Rˉraw,j−Rˉraw,j+1)/h\bar H=(\bar R_{{\rm raw},j}-\bar R_{{\rm raw},j+1})/h
(4)Rraw,j-=s(xj;μ)R_{{\rm raw},j}\mathrel{\text{-=}}s(x_j;\mu)R˙raw,j-=sμ(xj) μ˙\dot R_{{\rm raw},j}\mathrel{\text{-=}}s_\mu(x_j)\,\dot\muμˉ-=sμ(xj) Rˉraw,j\bar\mu\mathrel{\text{-=}}s_\mu(x_j)\,\bar R_{{\rm raw},j}
(5)R=QRraw+e0b0+eNbNR=QR_{\rm raw}+e_0b_0+e_Nb_NR˙=QR˙raw+e0b˙0+eNb˙N\dot R=Q\dot R_{\rm raw}+e_0\dot b_0+e_N\dot b_NRˉraw=QRˉ, bˉ0=Rˉ0, bˉN=RˉN\bar R_{\rm raw}=Q\bar R,\ \bar b_0=\bar R_0,\ \bar b_N=\bar R_N

覆盖(5)在程序最后执行,所以它的伴随语句(5′)最先执行:把种子分成两份。屏蔽后的种子 QRˉQ\bar R(保留第 11 到 N−1N-1 行)交给转置的面循环与源项;两个约束种子 bˉ0\bar b_0、bˉN\bar b_N 交给约束读到的节点:uˉ0+=bˉ0\bar u_0\mathrel{\text{+=}}\bar b_0、uˉin-=bˉ0\bar u_{\rm in}\mathrel{\text{-=}}\bar b_0,uˉN+=3bˉN/(2h)\bar u_N\mathrel{\text{+=}}3\bar b_N/(2h)、uˉN−1-=2bˉN/h\bar u_{N-1}\mathrel{\text{-=}}2\bar b_N/h、uˉN−2+=bˉN/(2h)\bar u_{N-2}\mathrel{\text{+=}}\bar b_N/(2h)。写进替换行的源项因此没有权重。整段代码的对偶恒等式:

The overwrite (5) runs last in the code, so its adjoint statement (5′) runs first: it splits the seed in two. The masked seed QRˉQ\bar R (rows 11 to N−1N-1) goes to the transposed face loop and the sources; the two constraint seeds bˉ0\bar b_0, bˉN\bar b_N go to the nodes the constraints read: uˉ0+=bˉ0\bar u_0\mathrel{\text{+=}}\bar b_0, uˉin-=bˉ0\bar u_{\rm in}\mathrel{\text{-=}}\bar b_0, uˉN+=3bˉN/(2h)\bar u_N\mathrel{\text{+=}}3\bar b_N/(2h), uˉN−1-=2bˉN/h\bar u_{N-1}\mathrel{\text{-=}}2\bar b_N/h, uˉN−2+=bˉN/(2h)\bar u_{N-2}\mathrel{\text{+=}}\bar b_N/(2h). A source written into a replaced row therefore gets no weight. The duality identity of the whole code:

RˉTR˙=RˉrawTR˙raw+bˉ0 b˙0+bˉN b˙N=uˉTu˙+μˉ μ˙+uˉin u˙in.\bar R^T\dot R=\bar R_{\rm raw}^T\dot R_{\rm raw}+\bar b_0\,\dot b_0+\bar b_N\,\dot b_N=\bar u^T\dot u+\bar\mu\,\dot\mu+\bar u_{\rm in}\,\dot u_{\rm in}.

下面两个面板在 N=8N=8 上执行这些语句:播放器逐条执行前向或伴随扫描;对偶面板用随机种子把恒等式分成三层核对。

The two panels below run these statements for N=8N=8: the player steps through the tangent or the adjoint sweep, and the duality panel checks the identity level by level with random seeds.

B.4 离散伴随:正负号约定、缩放与最后一个节点

B.4 The discrete adjoint: sign, scaling and the last node

记 A=RuA=R_u,Rμ=∂R/∂μR_\mu=\partial R/\partial\mu(PDE 行上是 −sμ(xj)-s_\mu(x_j),两个替换行上是 0)。切线方程 Av=−RμAv=-R_\mu,伴随方程 ATψ=−wA^T\psi=-w,

With A=RuA=R_u and Rμ=∂R/∂μR_\mu=\partial R/\partial\mu (−sμ(xj)-s_\mu(x_j) on the PDE rows, 0 on the two replaced rows): tangent Av=−RμAv=-R_\mu, adjoint ATψ=−wA^T\psi=-w, and

dJhdμ=ψTRμ=−∑j=1N−1ψj sμ(xj)=wTv.\frac{\mathrm dJ_h}{\mathrm d\mu}=\psi^TR_\mu=-\sum_{j=1}^{N-1}\psi_j\,s_\mu(x_j)=w^Tv .

本页的 JavaScript 实现在所有存储的网格上两种算法相差不超过 5e−14。

On every stored grid the page's JavaScript implementation gives the two to within 5e−14.

缩放。Jh+ψTR=Jh+∑jψjRjJ_h+\psi^TR=J_h+\sum_j\psi_jR_j,其中 Rj≈(qx−s)(xj)R_j\approx(q_x-s)(x_j) 是密度;连续的拉格朗日函数用梯形公式离散:

Scaling. Jh+ψTR=Jh+∑jψjRjJ_h+\psi^TR=J_h+\sum_j\psi_jR_j with Rj≈(qx−s)(xj)R_j\approx(q_x-s)(x_j) a density, while the continuous Lagrangian, discretised by the trapezoid rule, reads

J+∫01λ (qx−s) dx≈J+∑jh λ(xj) (qx−s)(xj)⟹ψj≈h λ(xj).J+\int_0^1\lambda\,(q_x-s)\,\mathrm dx\approx J+\sum_jh\,\lambda(x_j)\,(q_x-s)(x_j)\qquad\Longrightarrow\qquad \psi_j\approx h\,\lambda(x_j).

所以 ψj/h\psi_j/h 逼近 λ\lambda。第 5 节的行是对偶控制体上的积分(Rj≈h(qx−s)(xj)R_j\approx h(q_x-s)(x_j)),所以那里 ψj≈λ(xj)\psi_j\approx\lambda(x_j),没有 hh(第 16 节,A.7)。ψ\psi 的缩放跟着行的缩放走;符号跟着拉格朗日函数的符号走(两处相同)。精确地说:记 S=diag(1,h,…,h,1)S=\mathrm{diag}(1,h,\dots,h,1),把内部行乘以 hh 得 R~=SR\tilde R=SR、A~=SA\tilde A=SA;A~Tψ~=−w\tilde A^T\tilde\psi=-w 等价于 AT(Sψ~)=−wA^T(S\tilde\psi)=-w,即 ψ=Sψ~\psi=S\tilde\psi:ψ~j=ψj/h\tilde\psi_j=\psi_j/h(1≤j≤N−11\le j\le N-1),ψ~0=ψ0\tilde\psi_0=\psi_0,ψ~N=ψN\tilde\psi_N=\psi_N,而梯度 ψ~TR~μ=(Sψ~)TRμ=ψTRμ\tilde\psi^T\tilde R_\mu=(S\tilde\psi)^TR_\mu=\psi^TR_\mu 不变。所以 ψj/h\psi_j/h 就是积分行版本的伴随,与第 16 节同标度;两个约束行没有缩放,乘子 ψ0\psi_0、ψN\psi_N 在两种写法里是同一个数。

So ψj/h\psi_j/h approximates λ\lambda. The rows of Section 5 are integrals over the dual volumes (Rj≈h(qx−s)(xj)R_j\approx h(q_x-s)(x_j)), so there ψj≈λ(xj)\psi_j\approx\lambda(x_j) without hh (Section 16, A.7). The scaling of ψ\psi follows the scaling of the rows; the sign follows the sign of the Lagrangian (the same in both places). To be exact: let S=diag(1,h,…,h,1)S=\mathrm{diag}(1,h,\dots,h,1) and multiply the interior rows by hh, R~=SR\tilde R=SR, A~=SA\tilde A=SA; then A~Tψ~=−w\tilde A^T\tilde\psi=-w is equivalent to AT(Sψ~)=−wA^T(S\tilde\psi)=-w, that is ψ=Sψ~\psi=S\tilde\psi: ψ~j=ψj/h\tilde\psi_j=\psi_j/h (1≤j≤N−11\le j\le N-1), ψ~0=ψ0\tilde\psi_0=\psi_0, ψ~N=ψN\tilde\psi_N=\psi_N, while the gradient ψ~TR~μ=(Sψ~)TRμ=ψTRμ\tilde\psi^T\tilde R_\mu=(S\tilde\psi)^TR_\mu=\psi^TR_\mu does not change. So ψj/h\psi_j/h is the adjoint of the version with integral rows, on the scale of Section 16; the two constraint rows are not scaled, and the multipliers ψ0\psi_0, ψN\psi_N are the same numbers in both versions.

下面的实验台把这个引理摆出来:选 NN 与指数 pp,把内部行乘以 hph^p(p=0p=0 是基准自己的行,p=1p=1 是积分行),看 ψ~j\tilde\psi_j 贴着 λ\lambda 还是 hλh\lambda,而 ψ0\psi_0、ψN\psi_N 和梯度一点没变。

The lab below shows the lemma at work: choose NN and an exponent pp, multiply the interior rows by hph^p (p=0p=0 is the benchmark's own rows, p=1p=1 the integral rows), and watch ψ~j\tilde\psi_j follow λ\lambda or hλh\lambda while ψ0\psi_0, ψN\psi_N and the gradient do not move.

替换行的乘子不是 λ\lambda 的值。ATψ=−wA^T\psi=-w 的第 00、NN 个方程(AA 的第 00、NN 列)给出 ψ0→νλx(0)\psi_0\to\nu\lambda_x(0)、ψN→νλ(1)\psi_N\to\nu\lambda(1),正是 B.2 的 β0\beta_0、βN\beta_N。主基准 λx∗(0)=−1\lambda^*_x(0)=-1、λ∗(1)=−114\lambda^*(1)=-\frac{1}{14};在 N=16384N=16384 上 ψ0=−0.100000\psi_0=−0.100000、ψN/ν=−0.071429\psi_N/\nu=−0.071429。

The multipliers of the replaced rows are not values of λ\lambda. Equations 00 and NN of ATψ=−wA^T\psi=-w (columns 00 and NN of AA) give ψ0→νλx(0)\psi_0\to\nu\lambda_x(0) and ψN→νλ(1)\psi_N\to\nu\lambda(1): the β0\beta_0 and βN\beta_N of B.2. For the primary case λx∗(0)=−1\lambda^*_x(0)=-1 and λ∗(1)=−114\lambda^*(1)=-\frac{1}{14}; at N=16384N=16384, ψ0=−0.100000\psi_0=−0.100000 and ψN/ν=−0.071429\psi_N/\nu=−0.071429.

最后一个 PDE 节点。ATψ=−wA^T\psi=-w 的最后两个方程(AA 的最后两列)可以精确地解出(理论审阅第 6 节;check_dn.py 用 sympy 从残差重新推出):

The last PDE node. The last two equations of ATψ=−wA^T\psi=-w (the last two columns of AA) can be solved exactly (section 6 of the theory review; check_dn.py derives them again from the residual with sympy):

ψN=(2ν3h−uN3)ψN−1−2h3wN,(uN−12h−νh2)ψN−2+(2ν3h2+2uN3h)ψN−1=−wN−1−43wN.\psi_N=\Bigl(\frac{2\nu}{3h}-\frac{u_N}3\Bigr)\psi_{N-1}-\frac{2h}3w_N,\qquad \Bigl(\frac{u_{N-1}}{2h}-\frac{\nu}{h^2}\Bigr)\psi_{N-2}+\Bigl(\frac{2\nu}{3h^2}+\frac{2u_N}{3h}\Bigr)\psi_{N-1}=-w_{N-1}-\frac43w_N .

若 ψN−2/h→λ(1)\psi_{N-2}/h\to\lambda(1),第二式乘 h2h^2 后取极限得 ψN−1/h→32λ(1)\psi_{N-1}/h\to\tfrac32\lambda(1)——也就是比值 ψN−1/(hλ(xN−1))→32\psi_{N-1}/(h\lambda(x_{N-1}))\to\tfrac32(因为 λ(xN−1)→λ(1)\lambda(x_{N-1})\to\lambda(1)),第一式再给 ψN→νλ(1)\psi_N\to\nu\lambda(1)。这里还用到 w=O(h)w=O(h) 与 uNu_N 有界(审阅中也这样写)。前提 ψN−2/h→λ(1)\psi_{N-2}/h\to\lambda(1) 在数据上成立(N=16384N=16384 时 ψN−2/(hλ(xN−2))\psi_{N-2}/(h\lambda(x_{N-2})) 离 1 不到 3e−8,且 λ(xN−2)→λ(1)\lambda(x_{N-2})\to\lambda(1)),但没有证明:所以 32\tfrac32 是一个有条件的结论。

If ψN−2/h→λ(1)\psi_{N-2}/h\to\lambda(1), the second identity multiplied by h2h^2 gives ψN−1/h→32λ(1)\psi_{N-1}/h\to\tfrac32\lambda(1) in the limit, i.e. the ratio ψN−1/(hλ(xN−1))→32\psi_{N-1}/(h\lambda(x_{N-1}))\to\tfrac32 (as λ(xN−1)→λ(1)\lambda(x_{N-1})\to\lambda(1)), and the first then ψN→νλ(1)\psi_N\to\nu\lambda(1). This also uses w=O(h)w=O(h) and a bounded uNu_N, as the review states. The premise ψN−2/h→λ(1)\psi_{N-2}/h\to\lambda(1) holds on the data (at N=16384N=16384, ψN−2/(hλ(xN−2))\psi_{N-2}/(h\lambda(x_{N-2})) is within 3e−8 of 1, and λ(xN−2)→λ(1)\lambda(x_{N-2})\to\lambda(1)) but is not proved: the 32\tfrac32 is therefore a conditional result.

怎样理解:PDE 行到 xN−1x_{N-1} 为止。梯度 −∑jψjsμ(xj)-\sum_j\psi_js_\mu(x_j) 是 −∫λsμ-\int\lambda s_\mu 的一个求积公式,而端点 xNx_N 没有 PDE 行;梯形公式在端点的半个权重 h2λ(1)sμ(1)\tfrac h2\lambda(1)s_\mu(1) 就落在 ψN−1\psi_{N-1} 上:ψN−1≈hλ(1)+h2λ(1)\psi_{N-1}\approx h\lambda(1)+\tfrac h2\lambda(1)。最后一个节点上的“层”是离散伴随携带端点权重的方式,梯度仍是二阶(实测)。后果体现在误差范数上:ψj/h−λ(xj)\psi_j/h-\lambda(x_j) 在 PDE 节点 1≤j≤N−21\le j\le N-2 上是 O(h2)O(h^2)(实测:在最细的两层网格之间,这些节点上的最大误差的阶是 2.00,主、次基准相同),在最后一个 PDE 节点 j=N−1j=N-1 处趋于 λ(1)/2\lambda(1)/2;两个替换行处,范数用 ψN/ν−λ(1)\psi_N/\nu-\lambda(1)(数据上也是 O(h2)O(h^2))与 x0x_0 处的 0,而不是 ψ0/h\psi_0/h、ψN/h\psi_N/h(它们不是 λ\lambda 的值)。于是最大误差不收敛(趋于 ∣λ(1)∣/2|\lambda(1)|/2),L2L^2 误差 ≈12∣λ(1)∣ h1/2\approx\tfrac12|\lambda(1)|\,h^{1/2}(半阶),去掉这个节点则是二阶:

How to read it: the PDE rows stop at xN−1x_{N-1}. The gradient −∑jψjsμ(xj)-\sum_j\psi_js_\mu(x_j) is a quadrature of −∫λsμ-\int\lambda s_\mu, and the end node xNx_N has no PDE row; the half weight of the trapezoid rule at the end, h2λ(1)sμ(1)\tfrac h2\lambda(1)s_\mu(1), lands on ψN−1\psi_{N-1}: ψN−1≈hλ(1)+h2λ(1)\psi_{N-1}\approx h\lambda(1)+\tfrac h2\lambda(1). The layer at the last node is how the discrete adjoint carries the end weight, and the gradient stays second order (measured). The consequence shows in the error norms: ψj/h−λ(xj)\psi_j/h-\lambda(x_j) is O(h2)O(h^2) at the PDE nodes 1≤j≤N−21\le j\le N-2 (measured: between the two finest grids the maximum over these nodes has order 2.00 in both benchmarks) and tends to λ(1)/2\lambda(1)/2 at the last PDE node j=N−1j=N-1; at the two replaced rows the norms use ψN/ν−λ(1)\psi_N/\nu-\lambda(1) (also O(h2)O(h^2) on the data) and 00 at x0x_0, not ψ0/h\psi_0/h, ψN/h\psi_N/h (they are not values of λ\lambda). So the maximum error does not converge (it tends to ∣λ(1)∣/2|\lambda(1)|/2), the L2L^2 error is ≈12∣λ(1)∣ h1/2\approx\tfrac12|\lambda(1)|\,h^{1/2} (half order), and without that node it is second order:

图 111 · 最后一个节点上的层。(a) 主基准在 x=1 附近:节点上的 ψ_j/h(点)贴着 λ*(线),只有最后一个 PDE 节点偏离,偏离量约 λ(1)/2;方块是 Neumann 行的 ψ_N/ν,它逼近 λ(1)。(b) 存储数据的比值 ψ_(N-1)/(hλ(x_(N-1))) 趋于 3/2(两个基准)。(c) 存储的 L^2 误差与 1/2|λ(1)|h^(1/2)(虚线)重合;去掉节点 N-1 后(本页自己的计算)误差按 h^2 下降。−0.25−0.2−0.15−0.1−0.050.750.80.850.90.951xψj​/h 与 λ(a) 主基准在 x = 1 附近:最后一个 PDE 节点偏离,方块是 ψN​/νλ*(连续)ψj​/h,N = 16ψj​/h,N = 64ψj​/h,N = 25611.11.21.31.41.51.610102​103​104​N(b) ψN−1​/(h λ(xN−1​)) → 3/2主基准次基准10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​10102​103​104​N(c) 主基准的伴随 L² 误差L² 误差(存储)|λ(1)|/2 · h1/2​去掉节点 N − 1
图 111 · 最后一个节点上的层。(a) 主基准在 x=1x=1 附近:节点上的 ψj/h\psi_j/h(点)贴着 λ∗\lambda^*(线),只有最后一个 PDE 节点偏离,偏离量约 λ(1)/2\lambda(1)/2;方块是 Neumann 行的 ψN/ν\psi_N/\nu,它逼近 λ(1)\lambda(1)。(b) 存储数据的比值 ψN−1/(hλ(xN−1))\psi_{N-1}/(h\lambda(x_{N-1})) 趋于 32\tfrac32(两个基准)。(c) 存储的 L2L^2 误差与 12∣λ(1)∣h1/2\tfrac12|\lambda(1)|h^{1/2}(虚线)重合;去掉节点 N−1N-1 后(本页自己的计算)误差按 h2h^2 下降。
Figure 111 · The layer at the last node. (a) The primary case near x=1: the nodal ψ_j/h (dots) follow λ* (line) except at the last PDE node, which is off by about λ(1)/2; the squares are the ψ_N/ν of the Neumann row, which approach λ(1). (b) The stored ratio ψ_(N-1)/(hλ(x_(N-1))) tends to 3/2 (both cases). (c) The stored L^2 error lies on 1/2|λ(1)|h^(1/2) (dashed); without node N-1 (this page's own computation) the error falls like h^2.−0.25−0.2−0.15−0.1−0.050.750.80.850.90.951xψj​/h and λ(a) primary case near x = 1: the last PDE node is off; squares are ψN​/νλ* (continuous)ψj​/h, N = 16ψj​/h, N = 64ψj​/h, N = 25611.11.21.31.41.51.610102​103​104​N(b) ψN−1​/(h λ(xN−1​)) → 3/2primarysecondary10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​10102​103​104​N(c) adjoint L² error, primaryL² error (stored)|λ(1)|/2 · h1/2​without node N − 1
Figure 111 · The layer at the last node. (a) The primary case near x=1x=1: the nodal ψj/h\psi_j/h (dots) follow λ∗\lambda^* (line) except at the last PDE node, which is off by about λ(1)/2\lambda(1)/2; the squares are the ψN/ν\psi_N/\nu of the Neumann row, which approach λ(1)\lambda(1). (b) The stored ratio ψN−1/(hλ(xN−1))\psi_{N-1}/(h\lambda(x_{N-1})) tends to 32\tfrac32 (both cases). (c) The stored L2L^2 error lies on 12∣λ(1)∣h1/2\tfrac12|\lambda(1)|h^{1/2} (dashed); without node N−1N-1 (this page's own computation) the error falls like h2h^2.

N=16384N=16384 时:主基准比值 1.49945,L2L^2 误差除以 h\sqrt h 为 0.03570,而 ∣λ∗(1)∣/2=128=0.03571|\lambda^*(1)|/2=\frac{1}{28}=0.03571;次基准比值 1.49890,L2/h=0.03399L^2/\sqrt h=0.03399,∣λ(1)∣/2=0.03402|\lambda(1)|/2=0.03402。去掉节点 N−1N-1 后的 L2L^2 阶(相邻网格):主基准 2.01、2.00、2.00、2.00。这些是数值证据;理论审阅也明确说没有证明全场的收敛阶或这个层的下界。

At N=16384N=16384: the primary ratio is 1.49945 and the L2L^2 error divided by h\sqrt h is 0.03570, against ∣λ∗(1)∣/2=128=0.03571|\lambda^*(1)|/2=\frac{1}{28}=0.03571; the secondary ratio is 1.49890, with L2/h=0.03399L^2/\sqrt h=0.03399 against ∣λ(1)∣/2=0.03402|\lambda(1)|/2=0.03402. The L2L^2 orders without node N−1N-1 (successive grids), primary: 2.01, 2.00, 2.00, 2.00. These are numerical evidence; the theory review, too, says explicitly that neither the order of the whole field nor a lower bound of this layer is proved.

自己试:选网格、基准与 μ\mu,看状态、切线解和伴随,以及两个乘子与最后一个节点的比值。

Try it: choose the mesh, the case and μ\mu, and look at the state, the tangent and the adjoint, the two multipliers and the ratio at the last node.

B.5 存储的加密结果

B.5 The stored refinement runs

下表来自 results/refinement_q0.json(主基准);数据由 benchmark.py 生成,带实现文件的 SHA-256(implementation_sha256);结果文件本身的 SHA-256 由 data.js 在构建时计算(附录 C)。所有误差都在完整网格上计算,L2L^2 是节点上的梯形网格范数;伴随误差在 1≤j≤N−11\le j\le N-1 用 ψj/h−λ(xj)\psi_j/h-\lambda(x_j),在 xNx_N 用 ψN/ν−λ(1)\psi_N/\nu-\lambda(1),在 x0x_0 取 0(与 benchmark.py 相同;它存储的是相反的正负号)。本页自己的 JavaScript 格式在每个网格上重算了这些量:与存储值(目标、梯度、所有误差与采样剖面)的绝对差不到 2e−11。相对于 N=16384N=16384 的梯度误差(1.4e−9 与 8.7e−10,是两个 O(1)O(1) 数的微小差),差别可达 7e−3,所以表中最细网格梯度误差的阶(2.01)的最后一位是舍入噪声;对其余存储误差,本页重算的相对差都不到 9e−5。

The table comes from results/refinement_q0.json (primary case); the data were produced by benchmark.py and carry the SHA-256 of the implementation (implementation_sha256); the SHA-256 of the result file itself is computed by data.js at build time (Appendix C). Every error uses the full grid; L2L^2 is the trapezoidal grid norm over the nodes; the adjoint error is ψj/h−λ(xj)\psi_j/h-\lambda(x_j) for 1≤j≤N−11\le j\le N-1, ψN/ν−λ(1)\psi_N/\nu-\lambda(1) at xNx_N and 0 at x0x_0 (as in benchmark.py, which stores the opposite sign). This page's own JavaScript scheme recomputes these quantities on every grid: it agrees with the stored values (objective, gradient, every error and the sampled profiles) to within 2e−11 in absolute terms. Relative to the gradient errors at N=16384N=16384 (1.4e−9 and 8.7e−10, small differences of two O(1)O(1) numbers) the difference is up to 7e−3, so the last digit of the finest gradient-error order in the table (2.01) is rounding noise; for every other stored error the page's recomputation agrees to within 9e−5 relative.

NN状态 L2L^2State L2L^2阶Order目标误差Objective error梯度误差Gradient error阶Order伴随 L2L^2Adjoint L2L^2阶OrderψN−1/(hλ(xN−1))\psi_{N-1}/(h\lambda(x_{N-1}))ψN−1/(hλ(xN−1))\psi_{N-1}/(h\lambda(x_{N-1}))
168.25e−5—5.30e−41.51e−3—7.92e−3—1.25191
322.06e−52.001.33e−43.78e−42.005.59e−30.501.32358
645.16e−62.003.31e−59.45e−52.004.13e−30.431.39078
1281.29e−62.008.28e−62.36e−52.003.03e−30.451.43840
2563.22e−72.002.07e−65.90e−62.002.18e−30.471.46715
5128.06e−82.005.18e−71.48e−62.001.56e−30.481.48301
10242.01e−82.001.29e−73.69e−72.001.11e−30.491.49136
20485.04e−92.003.24e−89.22e−82.007.87e−40.501.49564
40961.26e−92.008.09e−92.31e−82.005.57e−40.501.49781
81923.15e−102.002.02e−95.77e−92.003.94e−40.501.49890
163847.87e−112.005.06e−101.44e−92.012.79e−40.501.49945
图 112 · 存储的加密结果(N=16 到 16384)。状态、目标与梯度误差按 h^2 下降(点线是 h^2 参考);伴随的 L^2 误差只有半阶,原因是 B.4 的最后一个节点。两个基准的表现相同。10-11​10-10​10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​10102​103​104​N主基准(ω = q0​,ν = 0.1)h²状态 L²目标梯度伴随 L²10-11​10-10​10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​10102​103​104​N次基准(ω = 1 + x,ν = 0.05)h²状态 L²目标梯度伴随 L²
图 112 · 存储的加密结果(N=16N=16 到 16384)。状态、目标与梯度误差按 h2h^2 下降(点线是 h2h^2 参考);伴随的 L2L^2 误差只有半阶,原因是 B.4 的最后一个节点。两个基准的表现相同。
Figure 112 · The stored refinement runs (N=16 to 16384). The errors of the state, the objective and the gradient fall like h^2 (dotted: an h^2 reference); the L^2 error of the adjoint falls only at half order, because of the last node of B.4. Both cases behave alike.10-11​10-10​10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​10102​103​104​Nprimary (ω = q0​, ν = 0.1)h²state L²objectivegradientadjoint L²10-11​10-10​10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​10102​103​104​Nsecondary (ω = 1 + x, ν = 0.05)h²state L²objectivegradientadjoint L²
Figure 112 · The stored refinement runs (N=16N=16 to 16384). The errors of the state, the objective and the gradient fall like h2h^2 (dotted: an h2h^2 reference); the L2L^2 error of the adjoint falls only at half order, because of the last node of B.4. Both cases behave alike.

播放器沿着 NN 逐帧前进,左边是存储剖面在 x=1x=1 附近的伴随密度,右边是到当前帧为止的误差:

The player steps through NN; on the left the adjoint density of the stored profile near x=1x=1, on the right the errors so far:

B.6 差分核对

B.6 The finite-difference check

数据里还有 N=256N=256 上的步长扫描:每个步长 τ\tau 都完整地重新求解两次(μ±τ\mu\pm\tau,从基解热启动),中心差分与伴随梯度比较。

The data also hold a step scan at N=256N=256: for every step τ\tau the nonlinear problem is re-solved twice (μ±τ\mu\pm\tau, warm-started from the base root) and the central difference is compared with the adjoint gradient.

图 113 · 存储的差分步长扫描(N=256)。大步长时误差按 τ^2(截断)下降,小步长时按 1/τ(舍入)上升;最好的一点在 τ=10^(-4),与伴随梯度相差 8.2e−14(主基准)与 2.7e−13(次基准)。本页的格式(以及 check_dn.py 的独立格式)重算了最大的三个步长(τ ≥ 10^(-4);前两个截断主导),与存储值相差不到 7e−12。10-14​10-13​10-12​10-11​10-10​10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​τ|差分 − 伴随|截断 ∝ τ²舍入 ∝ 1/τ完整重算的中心差分(两次 Newton 求解)与伴随梯度之差:存储的步长扫描主基准,N = 256次基准,N = 256
图 113 · 存储的差分步长扫描(N=256N=256)。大步长时误差按 τ2\tau^2(截断)下降,小步长时按 1/τ1/\tau(舍入)上升;最好的一点在 τ=10−4\tau=10^{-4},与伴随梯度相差 8.2e−14(主基准)与 2.7e−13(次基准)。本页的格式(以及 check_dn.py 的独立格式)重算了最大的三个步长(τ≥10−4\tau\ge10^{-4};前两个截断主导),与存储值相差不到 7e−12。
Figure 113 · The stored finite-difference step scan (N=256). For large steps the error falls like τ^2 (truncation), for small steps it rises like 1/τ (rounding); the best point, at τ=10^(-4), differs from the adjoint gradient by 8.2e−14 (primary) and 2.7e−13 (secondary). This page's scheme (and the independent scheme of check_dn.py) recomputes the three largest steps (τ ≥ 10^(-4); the first two truncation-dominated) and agrees with the stored values to within 7e−12.10-14​10-13​10-12​10-11​10-10​10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​τ|FD − adjoint|truncation ∝ τ²rounding ∝ 1/τfull re-solve central differences (two Newton solves) against the adjoint gradient: the stored step scanprimary, N = 256secondary, N = 256
Figure 113 · The stored finite-difference step scan (N=256N=256). For large steps the error falls like τ2\tau^2 (truncation), for small steps it rises like 1/τ1/\tau (rounding); the best point, at τ=10−4\tau=10^{-4}, differs from the adjoint gradient by 8.2e−14 (primary) and 2.7e−13 (secondary). This page's scheme (and the independent scheme of check_dn.py) recomputes the three largest steps (τ≥10−4\tau\ge10^{-4}; the first two truncation-dominated) and agrees with the stored values to within 7e−12.

B.7 理论审阅:哪些成立,核对了哪些

B.7 The theory review: what holds, what was checked

包里的 THEORY_REVIEW.md 给出一份手写的证明。它的离散部分在三个条件下成立:0≤μ≤120\le\mu\le\tfrac12、h<2ν/(1+μ)h<2\nu/(1+\mu)、h≤ν2/(4μ2)h\le\nu^2/(4\mu^2);对 μ=0.2\mu=0.2,主基准要 N≥16N\ge16,次基准要 N≥64N\ge64(本页按条件重新算出)。证明的链条是:在精确解的节点值 y∗y^* 处,约化 Jacobian A0A_0 是非奇异 M 矩阵——h<2ν/(1+μ)h<2\nu/(1+\mu) 时相邻非对角元严格为负(不可约),其余非对角元为零,行和非负,且第一行的行和 ν/h2+u2/(2h)>0\nu/h^2+u_2/(2h)>0;比较函数(闸函数)x(2−x)x(2-x) 给出 ∥A0−1∥∞≤1/(2ν)\|A_0^{-1}\|_\infty\le1/(2\nu);冻结 Jacobian 的 Newton 映射在半径 ρ=2μ2h2/ν\rho=2\mu^2h^2/\nu 的球内是压缩映射(压缩因子 η=ρ/(νh)=2μ2h/ν2≤12\eta=\rho/(\nu h)=2\mu^2h/\nu^2\le\tfrac12,审阅记作 qq),所以球内有唯一的离散根,且

THEORY_REVIEW.md in the package gives a handwritten proof. Its discrete part holds under three conditions: 0≤μ≤120\le\mu\le\tfrac12, h<2ν/(1+μ)h<2\nu/(1+\mu) and h≤ν2/(4μ2)h\le\nu^2/(4\mu^2); for μ=0.2\mu=0.2 this means N≥16N\ge16 for the primary case and N≥64N\ge64 for the secondary (recomputed here from the conditions). The chain of the proof: at the exact sample y∗y^* the reduced Jacobian A0A_0 is a nonsingular M-matrix: its neighbouring off-diagonal entries are strictly negative when h<2ν/(1+μ)h<2\nu/(1+\mu) (so it is irreducible), all other off-diagonal entries vanish, all row sums are nonnegative and the first, ν/h2+u2/(2h)\nu/h^2+u_2/(2h), is positive; the barrier (comparison) function x(2−x)x(2-x) gives ∥A0−1∥∞≤1/(2ν)\|A_0^{-1}\|_\infty\le1/(2\nu); the frozen Newton map is a contraction in the ball of radius ρ=2μ2h2/ν\rho=2\mu^2h^2/\nu (contraction factor η=ρ/(νh)=2μ2h/ν2≤12\eta=\rho/(\nu h)=2\mu^2h/\nu^2\le\tfrac12, the review's qq), so the ball holds a unique discrete root, and

∥u^−uμ∗∥∞≤53ρ,∥vh−v∗∥∞≤53Ev,Ev=4μh2ν+4μ2hν2,∣gh−g∣≤53WhEv+h212∥(ωv∗)xx∥∞,\|\hat u-u^*_\mu\|_\infty\le\tfrac53\rho,\qquad \|v_h-v^*\|_\infty\le\tfrac53E_v,\quad E_v=\frac{4\mu h^2}{\nu}+\frac{4\mu^2h}{\nu^2},\qquad |g_h-g|\le\tfrac53W_hE_v+\frac{h^2}{12}\bigl\|(\omega v^*)_{xx}\bigr\|_\infty,

其中 Wh=∑j∣wj∣≤∥ω∥∞W_h=\sum_j|w_j|\le\|\omega\|_\infty。梯度界只有 O(h)O(h):它不预测实测的二阶。主基准写成显式常数:∣gh−5472100∣≤68021h+7091420h2|g_h-\frac{547}{2100}|\le\tfrac{680}{21}h+\tfrac{7091}{420}h^2(N≥16N\ge16)。我们核对了什么,见下表:

with Wh=∑j∣wj∣≤∥ω∥∞W_h=\sum_j|w_j|\le\|\omega\|_\infty. The gradient bound is only O(h)O(h): it does not predict the measured second order. For the primary case with explicit constants: ∣gh−5472100∣≤68021h+7091420h2|g_h-\frac{547}{2100}|\le\tfrac{680}{21}h+\tfrac{7091}{420}h^2 (N≥16N\ge16). What was checked, and how:

审阅的说法Claim of the review本页的核对Check on this page结论Status
精确解、源项、ω\omega(q0q_0)、J(μ)J(\mu)、梯度 5472100\frac{547}{2100}、1312\frac{13}{12}、λ∗\lambda^* 与 Robin 条件exact state, source, ω\omega (q0q_0), J(μ)J(\mu), gradients 5472100\frac{547}{2100}, 1312\frac{13}{12}, λ∗\lambda^* and the Robin conditionsympy 有理数(check_dn.py A1–A6);本页 BigInt 有理数(figs_g.js)sympy rationals (check_dn.py A1–A6); BigInt rationals of this page (figs_g.js)精确成立holds exactly
Green 恒等式、伴随的两个边界条件、能量恒等式Green identity, the two adjoint boundary conditions, the energy identity对一般多项式的 sympy 恒等式(A7–A9)sympy identities for general polynomials (A7–A9)精确成立holds exactly
精确解节点值的残差 2μ2h2(xj−1)2\mu^2h^2(x_j-1)、行和、约化的最后一行、比较函数(闸函数)不等式 A0x(2−x)≥2νA_0x(2-x)\ge2\nuexact-sample residual 2μ2h2(xj−1)2\mu^2h^2(x_j-1), row sums, the reduced last row, the barrier A0x(2−x)≥2νA_0x(2-x)\ge2\nu符号推导(A10–A13);数值,N = 16–1024(E1–E5)symbolic (A10–A13); numerical, N = 16–1024 (E1–E5)成立holds
M 矩阵、∥A0−1∥∞≤1/(2ν)\|A_0^{-1}\|_\infty\le1/(2\nu)、球内唯一根、∥A(y^)−1∥∞≤1/ν\|A(\hat y)^{-1}\|_\infty\le1/\nuM-matrix, ∥A0−1∥∞≤1/(2ν)\|A_0^{-1}\|_\infty\le1/(2\nu), unique root in the ball, ∥A(y^)−1∥∞≤1/ν\|A(\hat y)^{-1}\|_\infty\le1/\nu读过论证;在每个满足条件、N ≤ 1024 的网格上数值核对(E1–E7)argument read; checked numerically on every grid meeting the conditions with N ≤ 1024 (E1–E7)成立;证明本页未重写holds; the proof is not rewritten here
∥u^−u∗∥∞≤53ρ\|\hat u-u^*\|_\infty\le\tfrac53\rho、∥vh−v∗∥∞≤53Ev\|v_h-v^*\|_\infty\le\tfrac53E_v、∣gh−g∣|g_h-g| 的 O(h)O(h) 界、目标的界∥u^−u∗∥∞≤53ρ\|\hat u-u^*\|_\infty\le\tfrac53\rho, ∥vh−v∗∥∞≤53Ev\|v_h-v^*\|_\infty\le\tfrac53E_v, the O(h)O(h) bound of ∣gh−g∣|g_h-g|, the objective bounds存储数据上每个满足条件的网格(D1–D5);界至少是实测误差的 48 倍(状态)和 598 倍(梯度)every grid of the stored data meeting the conditions (D1–D5); the bounds exceed the measured errors at least 48-fold (state) and 598-fold (gradient)成立(保守)holds (conservative)
最后两列的精确恒等式;32\tfrac32 层(以 ψN−2/h→λ(1)\psi_{N-2}/h\to\lambda(1) 为前提)the exact identities of the last two columns; the 32\tfrac32 layer (with the premise ψN−2/h→λ(1)\psi_{N-2}/h\to\lambda(1))sympy(A14);数据与本页计算(C3)sympy (A14); data and this page’s runs (C3)恒等式成立;条件在数据上成立,未证明identities hold; the condition holds on the data, unproved
梯度的二阶收敛、伴随场的阶、层的下界、全局唯一性、Newton 迭代进入该球、浮点执行second-order gradient, orders of the adjoint field, a lower bound of the layer, global uniqueness, the Newton program entering the ball, floating-point execution只有数值证据numerical evidence only审阅中明确列为未证明;本页也不证明stated as unproved in the review; not proved here either
图 114 · 理论审阅的界(虚线)与实测误差(点),只画满足条件的网格(主基准 N ≥ 16,次基准 N ≥ 64)。状态界与实测平行(都是 h^2),但界是实测的 48–89 倍;梯度界是 O(h),实测是 O(h^2),差距随加密变大。界都成立;它们是保证,不是预测。10-11​10-10​10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​10102​103​104​N状态:‖û − u*‖∞ 与 (5/3)ρ界,主实测,主界,次实测,次10-10​10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​11010102​103​104​N梯度:|gh​ − g| 与 O(h) 界界,主实测,主界,次实测,次
图 114 · 理论审阅的界(虚线)与实测误差(点),只画满足条件的网格(主基准 N≥16N\ge16,次基准 N≥64N\ge64)。状态界与实测平行(都是 h2h^2),但界是实测的 48–89 倍;梯度界是 O(h)O(h),实测是 O(h2)O(h^2),差距随加密变大。界都成立;它们是保证,不是预测。
Figure 114 · The bounds of the theory review (dashed) and the measured errors (dots), only on grids meeting the conditions (primary N ≥ 16, secondary N ≥ 64). The state bound runs parallel to the measurement (both h^2) but 48–89 times higher; the gradient bound is O(h) while the measurement is O(h^2), so the gap widens under refinement. All bounds hold; they are guarantees, not predictions.10-11​10-10​10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​10102​103​104​Nstate: ‖û − u*‖∞ and (5/3)ρbound, primarymeasured, primarybound, secondarymeasured, secondary10-10​10-9​10-8​10-7​10-6​10-5​10-4​10-3​10-2​10-1​11010102​103​104​Ngradient: |gh​ − g| and the O(h) boundbound, primarymeasured, primarybound, secondarymeasured, secondary
Figure 114 · The bounds of the theory review (dashed) and the measured errors (dots), only on grids meeting the conditions (primary N≥16N\ge16, secondary N≥64N\ge64). The state bound runs parallel to the measurement (both h2h^2) but 48–89 times higher; the gradient bound is O(h)O(h) while the measurement is O(h2)O(h^2), so the gap widens under refinement. All bounds hold; they are guarantees, not predictions.

改一改条件看看:实验台对任意 NN、μ\mu、ν\nu 判断三个条件,算出 ρ\rho、η\eta 与三个界(状态、切线解、梯度),并用本页的格式算出实际误差。

Change the conditions: the lab judges the three conditions for any NN, μ\mu and ν\nu, evaluates ρ\rho, η\eta and the three bounds (state, tangent, gradient), and runs the page's scheme for the actual errors.

本附录的结论:审阅里本页能核对的代数与不等式全部成立,没有发现错误;需要保留的只是结论的强弱:32\tfrac32 层与半阶 L2L^2 由最后一个节点完全解释,但以未证明的 ψN−2/h→λ(1)\psi_{N-2}/h\to\lambda(1) 为前提;梯度的严格界只有 O(h)O(h),而且很保守。数值结果是证据,不是证明。

The outcome of this appendix: every piece of algebra and every inequality of the review that this page can check holds, and no error was found. What needs saying is a matter of degree: the 32\tfrac32 layer and the half-order L2L^2 are fully explained by the last node but rest on the unproved premise ψN−2/h→λ(1)\psi_{N-2}/h\to\lambda(1), and the rigorous gradient bound is only O(h)O(h) and very conservative. Numerical results are evidence, not proofs.

附录 C:复现与数据

Appendix C: Reproduction and data

本节实验:页面上的一个数字从哪里来?挑一个——比如附录 B 里 N=16384N=16384 的梯度误差——按图 115 追到产生它的程序、记录它的文件和核对它的检查。

Experiment: where does a number on this page come from? Pick one, say the gradient error of Appendix B at N=16384N=16384, and follow Figure 115 to the program that produced it, the file that records it and the check that holds it.

本页的数字有三个来源:浏览器里的模型(model.js,正文各节与附录 A 的连续伴随)、附录的数值(figs_g.js),以及独立的 Python 包算出的大网格数据(格点格式的 node/、附录 B 的 paper_dn/,以及格心页的包,后者只用于两种格式的对比;A.7 的对比还在构建时运行格心页自己的模型,并把实验台要用的结果嵌入页面)。三者各有核对;本附录把它们列清楚,并给出复现的命令。

The numbers of this page have three sources: the model in the browser (model.js: the main sections and the continuous adjoint of Appendix A), the numerics of the appendices (figs_g.js), and the large-grid data of independent Python packages (node/ for the node scheme, paper_dn/ for Appendix B, and the package of the cell-centred page, read only for the comparisons of the two schemes; the comparison of A.7 also runs the model of the cell-centred page at build time and embeds what its lab needs). Each is checked; this appendix lists how, and gives the commands to reproduce them.

图 115 · 数字的来路。上排:Python 包写出带出处的 JSON,data.js 在每次构建时核对哈希与标注,构建程序把数字写进页面。中排:浏览器里运行的两份代码(model.js、figs_g.js)与构建程序 build.js。下排:把它们与独立计算核对的检查(箭头指向被核对的对象);check_g.js 与 check_dn.py 还把存储的 JSON 结果逐项重算。Python 包python/burgers_viscous/node/solve_node.py(本页)paper_dn/benchmark.py(附录 B)solve.py(格心页,对比用)结果文件(JSON)命令、版本、UTC 时间实现的 SHA-256mathematical_proof = false误差、剖面、Newton 历史data.js每次构建都核对:实现哈希与文件一致标注为数值证据字段齐全、无 NaN/Infmodel.js浏览器里的模型:残差、前向、伴随、求解、连续伴随(谱方法)SHA-256 68bb86ba7c05…figs_g.js附录的数值:切线配点法、积分因子、A.7 的伴随、格点基准、有理数、SHA-256构建 build.jslesson_*.js 写正文与图数字来自模型与数据记入 facts.json→ adjoint_burgers_viscous_node.html独立的 Python 审计audit/ref_model.py → reference.jsonaudit/audit_g.pycheck_dn.py(sympy +另一套格点格式)JavaScript 检查check_model.js (--selftest)check_g.js (--selftest)把模型与附录数值与独立计算核对页面上的检查tools/probe.jsexperiments/check_site_widths.js无控制台错误、无空面板、手机宽度不横向滚动
图 115 · 数字的来路。上排:Python 包写出带出处的 JSON,data.js 在每次构建时核对哈希与标注,构建程序把数字写进页面。中排:浏览器里运行的两份代码(model.js、figs_g.js)与构建程序 build.js。下排:把它们与独立计算核对的检查(箭头指向被核对的对象);check_g.js 与 check_dn.py 还把存储的 JSON 结果逐项重算。
Figure 115 · Where the numbers come from. Top: the Python packages write JSON with its provenance, data.js checks hashes and labels at every build, and the builder writes the numbers into the page. Middle: the two pieces of code that run in the browser (model.js, figs_g.js) and the builder build.js. Bottom: the checks that hold them to independent computations (the arrows point at what is checked); check_g.js and check_dn.py also recompute the stored JSON results one by one.Python packagespython/burgers_viscous/node/solve_node.py (this page)paper_dn/benchmark.py (App. B)solve.py (cell page, comparison)result files (JSON)command, versions, UTC timeSHA-256 of the implementationmathematical_proof = falseerrors, profiles, Newton historydata.jschecked at every build:implementation hash matcheslabelled numerical evidencefields present and finitemodel.jsthe browser model: residual,tangent, adjoint, solves,continuous adjoint (spectral)SHA-256 68bb86ba7c05…figs_g.jsappendix numerics: tangentcollocation, integrating factor,A.7 adjoint, nodal benchmark,rationals, SHA-256build: build.jslesson_*.js write text, figuresnumbers from model and dataregistered in facts.json→ adjoint_burgers_viscous_node.htmlindependent Python auditsaudit/ref_model.py → reference.jsonaudit/audit_g.pycheck_dn.py (sympy +a second nodal scheme)JavaScript gatescheck_model.js (--selftest)check_g.js (--selftest)hold the model and the appendixnumerics to independent onesgates on the pagetools/probe.jsexperiments/check_site_widths.jsno console error, no empty lab,no sideways scroll on phones
Figure 115 · Where the numbers come from. Top: the Python packages write JSON with its provenance, data.js checks hashes and labels at every build, and the builder writes the numbers into the page. Middle: the two pieces of code that run in the browser (model.js, figs_g.js) and the builder build.js. Bottom: the checks that hold them to independent computations (the arrows point at what is checked); check_g.js and check_dn.py also recompute the stored JSON results one by one.

C.1 Python 包

C.1 The Python packages

格点格式的包位于 python/burgers_viscous/node/,附录 B 的包位于 python/burgers_viscous/paper_dn/,都与页面一起发布,只依赖 NumPy 与 SciPy(附录 B 的检查还要 SymPy)。格心页的包(python/burgers_viscous/ 里的 solve.py 与 examples/)只为两种格式的对比而读,见格心页的附录 C。各文件的作用:

The package of the node scheme is python/burgers_viscous/node/ and that of Appendix B is python/burgers_viscous/paper_dn/; both are published with the page and need only NumPy and SciPy (the checks of Appendix B also use SymPy). The package of the cell-centred page (solve.py and examples/ in python/burgers_viscous/) is read only for the comparisons of the two schemes; see Appendix C of the cell-centred page. What each file does:

文件File作用Role
README.md方程、格式、命令与限制equation, scheme, commands and limits
requirements.txt依赖:NumPy、SciPydependencies: NumPy, SciPy
solve_node.py正文的格点格式(残差、Newton、前向与伴随、加密研究、完整重算的差分核对):稀疏矩阵实现,与 model.js 互相独立;写出 examples/ 的数据the node-centred model of the main text (residual, Newton, tangent and adjoint, refinement study, FD check with full re-solves): a sparse implementation, independent of model.js; writes the data of examples/
test_solver_node.py单元测试unit tests
node/examples/格点格式的存储数据 large_65536.json、refinement_first.json、refinement_none.json、refinement_smooth.json;其中四个另有 CSV 版本(large_65536.csv、refinement_first.csv、refinement_none.csv、refinement_smooth.csv)the stored data of the node scheme large_65536.json, refinement_first.json, refinement_none.json, refinement_smooth.json; four of them also as CSV (large_65536.csv, refinement_first.csv, refinement_none.csv, refinement_smooth.csv)
paper_dn/benchmark.py附录 B 的格点基准(另一个模型)the nodal benchmark of Appendix B (a different model)
paper_dn/test_dn.py格点基准的单元测试unit tests of the nodal benchmark
paper_dn/check_algebra.py精确有理数核对(结果在 algebra_checks.json)exact rational checks (results in algebra_checks.json)
paper_dn/THEORY_REVIEW.md理论审阅(附录 B.7 核对了它)the theory review (audited in Appendix B.7)
paper_dn/README.md格点基准的说明与命令description and commands of the nodal benchmark
paper_dn/results/格点基准的结果:refinement_q0.json、refinement_one_x.json、refinement_q0.csv、refinement_one_x.csv、refinement_q0_fd.csv、refinement_one_x_fd.csvthe results of the nodal benchmark: refinement_q0.json, refinement_one_x.json, refinement_q0.csv, refinement_one_x.csv, refinement_q0_fd.csv, refinement_one_x_fd.csv

与第 5 节的规则相比,有一处不同。solve_node.py 遵循第 5 节的 Newton 规则(回溯线搜索、正状态盒、修正量的容差),只多一条:试探步在 max⁡∣R∣\max|R| 低于舍入下限时也被接受,这个下限是机器 epsilon 的 16 倍乘以 (1+ν/h)(1+\nu/h)。它只对 N=65536N=65536 的完整重算差分有用:没有它,这些重算的线搜索会失败;在 N=32,64,…,32768N=32,64,\dots,32768 的各个网格上,有没有这一条,解、Newton 历史与差分检验的结果都逐位相同(audit/audit_g.py)。

One deviation from the rule of Section 5. solve_node.py follows the Newton rule of Section 5 (backtracking line search, the positive state box, the tolerance on the correction) with one more clause: a trial step is also accepted when max⁡∣R∣\max|R| is below the rounding floor, 16 times the machine epsilon times (1+ν/h)(1+\nu/h). It matters only for the full re-solves of the finite differences at N=65536N=65536, which fail in the line search without it; on every mesh N=32,64,…,32768N=32,64,\dots,32768 the solution, the Newton history and the result of the finite-difference check are bit for bit the same with and without it (audit/audit_g.py).

独立的审计留在源码仓库里,不随页面发布(只有 python/ 作为 python/burgers_viscous/node/ 发布)。本页说“与独立计算核对”时指的就是下面这些文件:

The independent audit stays in the source repository and is not published with the page (only python/ is, as python/burgers_viscous/node/). These are the files that “held to an independent computation” refers to on this page:

文件(相对 viscous_node/)File (relative to viscous_node/)作用Role
audit/ref_model.py格点格式的稠密独立参考:由规格逐条语句写成,前向与伴随语句手写,复数步长 Jacobian;只用于小 NNthe dense independent reference of the node scheme, written from the specification statement by statement (tangent and reverse statements by hand, complex-step Jacobians); for small NN only
audit/make_reference.py、audit/reference.jsonaudit/make_reference.py, audit/reference.json写出 check_model.js 读取的测试向量write the test vectors that check_model.js reads
audit/audit_node.py参考对规格的核对(前向、伴随、复数步长、完整重算的有限差分、连续伴随、边界乘子);--sparse 另把稀疏实现与稠密参考逐项比较the checks of the reference against the specification (tangent, adjoint, complex step, finite differences with full re-solves, continuous adjoint, boundary multipliers); --sparse also compares the sparse implementation with the dense reference
audit/make_facts.py、audit/FACTS.mdaudit/make_facts.py, audit/FACTS.md由稠密参考与稀疏实现算出的核实过的数字(阶、乘子、精确节点值的残差)the verified numbers computed from the dense reference and the sparse implementation (orders, multipliers, residuals of the exact nodal values)
audit/audit_g.py、audit/reference_g.jsonaudit/audit_g.py, audit/reference_g.json附录 A、A.7 与 B.4 的独立审计(连续伴随、边界层常数、乘子与梯度的拆分、一阶恒等式、行缩放引理)the independent audit of Appendix A, A.7 and B.4 (continuous adjoint, layer constants, the multipliers and the split of the gradient, the first-order identity, the row-scaling lemma)
audit_dn/check_dn.py、dn_scheme.pyaudit_dn/check_dn.py, dn_scheme.py附录 B 的独立审计:sympy 代数、另一套格点格式、存储的运行、理论审阅the independent audit of Appendix B: sympy algebra, a second nodal scheme, the stored runs, the theory review

C.2 复现:命令与出处

C.2 Reproduction: commands and provenance

每个结果文件都记录了产生它的命令、程序版本、生成时间、Python/NumPy/SciPy 版本、平台和实现文件的 SHA-256,并标注 mathematical_proof = false。下面的命令直接取自这些记录(解释器路径换成 python3);格点格式的命令在包的 node/ 目录里运行,格点基准的命令在 paper_dn/ 里运行:

Every result file records the command that produced it, the program version, the generation time, the Python/NumPy/SciPy versions, the platform and the SHA-256 of the implementation, and is labelled mathematical_proof = false. The commands below are taken from these records (with the interpreter path replaced by python3); run the commands of the node scheme in the node/ directory of the package and those of the nodal benchmark in paper_dn/:

# node/examples/refinement_none.json  (2026-10-03T22:53:59Z)
python3 solve_node.py \
    --grids 32,64,128,256,512,1024,2048,4096,8192,16384 --nu 0.01 \
    --amplitude 0.2 --phase 0.07 --reconstruction none \
    --gradient-check --continuous-adjoint \
    --output examples/refinement_none.json

# node/examples/refinement_first.json  (2026-10-03T22:54:00Z)
python3 solve_node.py \
    --grids 32,64,128,256,512,1024,2048,4096,8192,16384 --nu 0.01 \
    --amplitude 0.2 --phase 0.07 --reconstruction first \
    --gradient-check --continuous-adjoint \
    --output examples/refinement_first.json

# node/examples/refinement_smooth.json  (2026-10-03T22:54:01Z)
python3 solve_node.py \
    --grids 32,64,128,256,512,1024,2048,4096,8192,16384 --nu 0.01 \
    --amplitude 0.2 --phase 0.07 --reconstruction smooth \
    --gradient-check --continuous-adjoint \
    --output examples/refinement_smooth.json

# node/examples/large_65536.json  (2026-10-03T22:54:03Z)
python3 solve_node.py --cells 65536 --nu 0.01 --amplitude 0.2 \
    --phase 0.07 --reconstruction none --gradient-check \
    --output examples/large_65536.json

# paper_dn/results/refinement_q0.json  (2026-10-02T09:05:57Z)
python3 benchmark.py \
    --grids 16,32,64,128,256,512,1024,2048,4096,8192,16384 --mu .2 \
    --nu .1 --objective q0 --fd-scan --fd-intervals 256 \
    --output results/refinement_q0.json

# paper_dn/results/refinement_one_x.json  (2026-10-02T09:06:34Z)
python3 benchmark.py \
    --grids 16,32,64,128,256,512,1024,2048,4096,8192,16384 --mu .2 \
    --nu .05 --objective one_x --fd-scan --fd-intervals 256 \
    --output results/refinement_one_x.json
文件File页面上的用途Used in生成(UTC)Generated (UTC)版本VersionPython / NumPy / SciPyPython / NumPy / SciPy
node/examples/refinement_none.json第 3、4、7、9、12、15–16、18 节,附录 A.7 及其图 108,C.2 的实验台与图 116(无限制器线性,N = 32 … 16384)Sections 3, 4, 7, 9, 12, 15–16 and 18, A.7 with Figure 108, the lab of C.2 and Figure 116 (unlimited linear, N = 32 … 16384)2026-10-03T22:53:59Z1.0.03.11.12 / 2.3.1 / 1.16.0
node/examples/refinement_first.json第 3、4、7、9、15–16、18 节,附录 A.7,C.2 的实验台与图 116(一阶,N = 32 … 16384)Sections 3, 4, 7, 9, 15–16 and 18, A.7, the lab of C.2 and Figure 116 (first order, N = 32 … 16384)2026-10-03T22:54:00Z1.0.03.11.12 / 2.3.1 / 1.16.0
node/examples/refinement_smooth.json第 3、4、7、9、15–16、18 节,附录 A.7,C.2 的实验台与图 116(光滑限制器,N = 32 … 16384)Sections 3, 4, 7, 9, 15–16 and 18, A.7, the lab of C.2 and Figure 116 (smooth limiter, N = 32 … 16384)2026-10-03T22:54:01Z1.0.03.11.12 / 2.3.1 / 1.16.0
node/examples/large_65536.json第 3、9、15–16 节与图 116(N = 65536)Sections 3, 9 and 15–16 and Figure 116 (N = 65536)2026-10-03T22:54:03Z1.0.03.11.12 / 2.3.1 / 1.16.0
paper_dn/results/refinement_q0.json附录 B、C.2 的实验台与图 116(主基准)Appendix B, the lab of C.2 and Figure 116 (primary case)2026-10-02T09:05:57Z1.0.03.14.3 / 2.4.6 / 1.18.1
paper_dn/results/refinement_one_x.json附录 B、C.2 的实验台与图 116(次基准)Appendix B, the lab of C.2 and Figure 116 (secondary case)2026-10-02T09:06:34Z1.0.03.14.3 / 2.4.6 / 1.18.1
examples/refinement_none.json格心页的包,用于两种格式的对比(N = 32 … 16384)the package of the cell-centred page, read for the comparisons of the two schemes (N = 32 … 16384)2026-10-02T08:35:50Z1.0.03.14.3 / 2.4.6 / 1.18.1
examples/refinement_first.json格心页的包,用于两种格式的对比(N = 32 … 4096)the package of the cell-centred page, read for the comparisons of the two schemes (N = 32 … 4096)2026-10-02T08:35:51Z1.0.03.14.3 / 2.4.6 / 1.18.1
examples/large_65536.json格心页的包,用于两种格式的对比(N = 65536)the package of the cell-centred page, read for the comparisons of the two schemes (N = 65536)2026-10-02T08:35:53Z1.0.03.14.3 / 2.4.6 / 1.18.1

SHA-256(构建时计算):页面读入的实现文件与结果文件。C.1 里的 CSV 文件与日志只是同一数据的另一种写法,本页不读取它们,这里也不计算它们的哈希。data.js 拒绝实现哈希与当前程序不符的数据,所以页面上的数字一定来自这些程序的当前版本。

SHA-256 (computed at build time): the implementation files and the result files the page reads. The CSV files and logs of C.1 are only another way of writing the same data; the page does not read them and no hash is computed for them here. data.js refuses data whose implementation hash differs from the current program, so the numbers on this page come from the current version of these programs.

文件(相对 python/burgers_viscous/)File (relative to python/burgers_viscous/)SHA-256SHA-256
examples/large_65536.json1241daca39fb2433ca6510c4edf58fac5475abf88d3a294596f2dc73dac5cd17
examples/refinement_first.json867fa572cfd7972361d20f954bb14905ef2b07bcb00ace4ac12d2fffbf6ff048
examples/refinement_none.json1bfc1b10868196bfd8527baa5b28d758e2505fdc4b21a0d3b5dd2502a78ecdfa
node/examples/large_65536.jsone2aa97c827d94747471641e19fb1b5e636e060b0eb90a522f87039fc4599eea0
node/examples/refinement_first.json25f2c6c6fd4e3ea604afed4e8ddfb7674dff21d6f7bdeae22c53353640421173
node/examples/refinement_none.json19cc697eb6fd3641b9f4e6a56f4491c32809b11279e3d02b188e07929f574768
node/examples/refinement_smooth.json29bd3d9e934caf315250f85f2e2e887b940fd9004b6763bcde0588801f5bbd82
node/solve_node.pya656f7615237a80558d7b51524a964509e3ee76aeb8663da12d0b5a9c2dc87ac
paper_dn/benchmark.pyfaa8f226d5f118975413c411a70e6a4758e0042cb04b00c0b3cc3027e0827246
paper_dn/results/refinement_one_x.json24f1f2159bcabfa1408cc2124dd32bbe4cb733feb3bd298bad45f4ad25e430fd
paper_dn/results/refinement_q0.jsonc49c72beeef091fd130306cbb0b8c31cabecdf81fcfd9156f7154403f3d953ab
solve.py0d36ac3febcd7e74c8f21cf95a1068554264c0982955dbbd6a7ebf9856586e3e
图 116 · 每次存储计算在生成数据的机器上的用时(JSON 里的 elapsed_seconds)。格点基准的时间包括两次完整重算的差分求解。这些是实测,不是性能保证;本页不依赖它们。每次存储计算在生成数据的机器上的用时(实测,不是性能保证)格点格式,无限制器线性格点格式,一阶格点格式,光滑限制器N = 65536格心包,无限制器线性(对比)格点基准,主(含两次差分求解)格点基准,次(含两次差分求解)0.0010.010.1110102​103​104​105​区间或单元数 N用时(s)
图 116 · 每次存储计算在生成数据的机器上的用时(JSON 里的 elapsed_seconds)。格点基准的时间包括两次完整重算的差分求解。这些是实测,不是性能保证;本页不依赖它们。
Figure 116 · The time of every stored run on the recording machine (elapsed_seconds of the JSON). The times of the nodal benchmark include the two full re-solves of the finite differences. These are measurements, not performance guarantees; nothing on this page depends on them.time of every stored run on the recording machine (measured, not a guarantee)node scheme, unlimited linearnode scheme, first ordernode scheme, smooth limiterN = 65536cell package, unlimited linear (comparison)nodal benchmark, primary (incl. 2 FD)nodal benchmark, secondary (incl. 2 FD)0.0010.010.1110102​103​104​105​intervals or cells Ntime (s)
Figure 116 · The time of every stored run on the recording machine (elapsed_seconds of the JSON). The times of the nodal benchmark include the two full re-solves of the finite differences. These are measurements, not performance guarantees; nothing on this page depends on them.

在浏览器里复现:选一次存储的计算,实验台用本页的代码重新求解,并逐位比较目标与梯度。

Reproduce in the browser: pick a stored run, the lab re-solves it with this page's code and compares the objective and the gradient digit by digit.

C.3 本页自己的检查

C.3 The page’s own checks

在源码目录 viscous_node/ 里运行(Node.js;Python 3 需要 NumPy、SciPy、SymPy):

Run in the source directory viscous_node/ (Node.js; Python 3 with NumPy, SciPy and SymPy):

# the page and its data (data.js checks every hash and label)
node build.js
# the browser model against the independent Python reference, and planted faults
node check_model.js
node check_model.js --selftest
# the numerics of the appendices (continuous adjoint, node-scheme multipliers, nodal benchmark, rationals, SHA-256)
node check_g.js
node check_g.js --selftest
# the independent Python audit of the node scheme: the reference against the specification, and the sparse implementation against the reference
python3 audit/audit_node.py
python3 audit/audit_node.py --sparse
python3 audit/make_facts.py
# the independent Python audit of the appendices (the node reference of audit/ and the cell-centred reference)
python3 audit/audit_g.py
# the audit of Appendix B: sympy algebra, a second nodal scheme, the stored runs, the theory review
python3 audit_dn/check_dn.py
python3 audit_dn/check_dn.py --selftest
# the independent Python reference (reference.json is what check_model.js reads)
python3 audit/make_reference.py
# every gate of the page, with and without the browser
node tools/gates.js
node tools/gates.js --quick
# the built page in headless Chrome: console errors, empty labs, both languages
node tools/probe.js
# the tests of the Python packages themselves (in the package directories)
python3 test_solver_node.py
python3 -m unittest -v test_dn.py
python3 check_algebra.py --check

C.4 各项说法如何核对

C.4 What is verified, and how

页面上的说法Claim on the page检查Check方式与容差How, tolerance
残差、Jacobian、前向与伴随语句(正文模型)residual, Jacobians, tangent and reverse statements (main model)check_model.js;audit/ref_model.pycheck_model.js; audit/ref_model.py与独立 Python 参考及复数步长比较,1e−12;点积检验 1e−14against the independent Python reference and complex step, 1e−12; the dot test to 1e−14
切线 = 伴随,与完整重算的差分比较tangent = adjoint, against FD with full re-solvescheck_model.js;audit/audit_node.pycheck_model.js; audit/audit_node.py前向、伴随与反向代码 1e−12;与 JhJ_h 的中心差分(完整重算)1e−8,光滑限制器的黏性轴要取 τ=10−6\tau=10^{-6}tangent, adjoint and reverse code 1e−12; central differences of JhJ_h with full re-solves 1e−8, where the viscosity axis of the smooth limiter needs τ=10−6\tau=10^{-6}
稀疏实现(格点格式的存储数据)the sparse implementation (the stored data of the node scheme)python/test_solver_node.py;audit/audit_node.py --sparse;check_g.js(A.7)python/test_solver_node.py; audit/audit_node.py --sparse; check_g.js (A.7)与稠密参考:Newton 解 1e−12,ψ\psi 1e−10,梯度 1e−11;与 model.js 在共同网格上的 ψ0\psi_0、ψN\psi_N 见 A.7against the dense reference: Newton solution 1e−12, ψ\psi 1e−10, gradient 1e−11; against model.js on the common meshes, ψ0\psi_0 and ψN\psi_N as in A.7
连续伴随(附录 A 的谱方法)continuous adjoint (the spectral solver of Appendix A)check_model.js;check_g.jscheck_model.js; check_g.js与 Python 求解器比较;与积分因子法比较 1e−10(相对)against the Python solver; against the integrating factor 1e−10 (relative)
梯度公式与边界项、对偶恒等式gradient formula with its boundary term, the duality identitycheck_g.js;audit/audit_g.pycheck_g.js; audit/audit_g.py与精确梯度比较 1e−12;切线解与伴随之差 1e−11against the exact gradient 1e−12; tangent against adjoint 1e−11
边界层的两项展开the two-term layer expansioncheck_g.jscheck_g.js数值:误差 /ν→γ1/\nu\to\gamma_1、剩余 /ν2/\nu^2 有界(形式推导,非证明)numerical: error/ν→γ1/\nu\to\gamma_1, remainder/ν2/\nu^2 bounded (formal derivation, not a proof)
A.7 的乘子 ψ0\psi_0、ψN\psi_N 与梯度的两部分、一阶恒等式the multipliers ψ0\psi_0, ψN\psi_N of A.7, the two parts of the gradient, the first-order identitycheck_g.js;audit/audit_g.pycheck_g.js; audit/audit_g.py与独立 Python 参考(节点与格心)比较 1e−9;恒等式 1e−12against the independent Python references (node and cell-centred) 1e−9; the identity 1e−12
格点基准的闭式(ϑ\vartheta、ω\omega、JJ、梯度、λ∗\lambda^*)closed forms of the nodal benchmark (ϑ\vartheta, ω\omega, JJ, gradients, λ∗\lambda^*)check_dn.py(sympy);check_g.js(BigInt)check_dn.py (sympy); check_g.js (BigInt)精确有理数exact rationals
格点基准的格式与存储结果;行缩放的恒等式the nodal benchmark scheme and the stored runs; the row-scaling identitycheck_g.js(JavaScript);check_dn.py(Python)check_g.js (JavaScript); check_dn.py (Python)N = 16 … 16384,1e−9;缩放恒等式 1e−12N = 16 … 16384, 1e−9; the scaling identity 1e−12
理论审阅的不等式与中间结论inequalities and intermediate claims of the theory reviewcheck_dn.py(D、E 组)check_dn.py (groups D, E)D 组:每个满足条件的网格;E 组:其中 N≤1024N\le1024 的网格group D: every grid meeting the conditions; group E: those with N≤1024N\le1024
数据的出处与完整性provenance and integrity of the datadata.js(每次构建)data.js (every build)SHA-256、标注、字段SHA-256, labels, fields
页面能运行、手机上不横向滚动the page runs, no sideways scroll on phonestools/probe.js;experiments/check_site_widths.jstools/probe.js; experiments/check_site_widths.js无控制台错误,375/360/320 pxno console error, 375/360/320 px

这些检查都是数值证据:它们说明代码与公式一致、与独立计算一致、与存储的数据一致,但不证明非线性问题或格式的存在性、唯一性或收敛定理。本页的证明是附录 A.4、附录 B 的精确代数,以及各节自己写出证明的地方(第 4–7 节:第 4 节一阶的稳定性证明、第 5 节的单步余项恒等式、第 6 节一阶 Jacobian 的 M 矩阵性质与 GS 收敛、第 7 节的精确代数);其余标明为“未证明”的地方,就是未证明。

All these checks are numerical evidence: they show that the code agrees with the formulas, with independent computations and with the stored data, but they do not prove existence, uniqueness or convergence theorems for the nonlinear problem or the scheme. The proofs on this page are those of Appendix A.4, the exact algebra of Appendix B, and those the sections themselves write out (Sections 4–7: the first-order stability proof of Section 4, the one-step remainder identity of Section 5, the M-matrix property and the Gauss–Seidel convergence of the first-order Jacobian in Section 6, the exact algebra of Section 7); whatever is labelled unproved is unproved.

C.5 浏览器模型的源码

C.5 The source of the browser model

下面是页面运行的 model.js 全文,SHA-256 为 68bb86ba7c055c1c002943d31c048d74faf00c3ce55cf3aa2003fa138d4952d2(构建时计算)。实验台可以在你的浏览器里重新计算这个哈希。

Below is the full model.js the page runs, with SHA-256 68bb86ba7c055c1c002943d31c048d74faf00c3ce55cf3aa2003fa138d4952d2 (computed at build time). The lab can recompute this hash in your browser.

model.js 全文(点击展开)model.js in full (click to open)
'use strict';
/* The NODE-centred viscous Burgers model of the page: the residual code, its tangent code and its reverse code, written statement by
   statement exactly as the page prints them (Sections 3, 5, 8, 9), and the solves built on them.  Nothing here is generated by an AD tool:
   viscous_node/audit/ (Python, written independently from SPEC.md: complex step, dot tests) holds every formula of this file to account, and
   check_model.js compares this file with it.

   Problem.  q(u) = u^2/2 - nu u_x,  q_x = s(x; D) on (0,1), u(0) = u_in, u(1) = u_out.  Manufactured: u*(x; D) = 1 + a sin(2 pi (x - phi)),
   D = (a, phi, nu), s = q*_x, u_in = u*(0), u_out = u*(1).  Objective J = int_0^1 (1 + x) u dx = 3/2 - a cos(2 pi phi)/(2 pi).
   Mesh.  N intervals of width h = 1/N; nodes x_j = j h (j = 0..N); U_j = the POINT value at node j (N + 1 unknowns, the two boundary rows are constraints);
   dual volume V_j = [x_j - h/2, x_j + h/2] intersected with [0,1]; face f (f = 0..N-1) between node f and node f+1, at x_{f+1/2} = (f + 1/2) h.
   Face flux  H_f = (qL^2 + qR^2)/4 - (qR - qL) - nu (UR - UL)/h        (Rusanov, fixed speed 2, plus the central viscous flux)
   Residual   R_j = H_j - H_{j-1} - (Q_j - Q_{j-1})  (1 <= j <= N-1),  Q_f = q*(x_{f+1/2}; D);   R_0 = U_0 - u_in,  R_N = U_N - u_out
   Objective  J_h = sum_j w_j U_j,  w_j = W_j (1 + x_j)  (the trapezoid rule for (1 + x) u). */
(function (root) {
  const TWO_PI = 2 * Math.PI;
  const NUM = typeof module !== 'undefined' ? require('../experiments/numerics') : root.EduNumerics;

  /* ---------- the exact functions of the manufactured solution (D = [a, phi, nu]) ---------- */
  const ustar = (x, D) => 1 + D[0] * Math.sin(TWO_PI * (x - D[1]));
  const ustarX = (x, D) => TWO_PI * D[0] * Math.cos(TWO_PI * (x - D[1]));
  const qstar = (x, D) => { const u = ustar(x, D); return 0.5 * u * u - D[2] * ustarX(x, D); };
  /* tangent of Q = q*(x; D) for the seed Dd and its reverse (accumulated into Db) */
  function qstarD(x, D, Dd) {
    const z = TWO_PI * (x - D[1]), s = Math.sin(z), c = Math.cos(z), u = 1 + D[0] * s;
    return (u * s - D[2] * TWO_PI * c) * Dd[0] + (u * (-TWO_PI * D[0] * c) - D[2] * TWO_PI * TWO_PI * D[0] * s) * Dd[1] + (-TWO_PI * D[0] * c) * Dd[2];
  }
  function qstarB(x, D, Qb, Db) {
    const z = TWO_PI * (x - D[1]), s = Math.sin(z), c = Math.cos(z), u = 1 + D[0] * s;
    Db[0] += (u * s - D[2] * TWO_PI * c) * Qb;
    Db[1] += (u * (-TWO_PI * D[0] * c) - D[2] * TWO_PI * TWO_PI * D[0] * s) * Qb;
    Db[2] += (-TWO_PI * D[0] * c) * Qb;
  }
  /* boundary data and their tangents: u_in = u*(0), u_out = u*(1) (equal, u* is periodic) */
  const uin = D => ustar(0, D), uout = D => ustar(1, D);
  const uinD = (D, Dd) => Math.sin(TWO_PI * (0 - D[1])) * Dd[0] + (-TWO_PI * D[0] * Math.cos(TWO_PI * (0 - D[1]))) * Dd[1];
  const uoutD = (D, Dd) => Math.sin(TWO_PI * (1 - D[1])) * Dd[0] + (-TWO_PI * D[0] * Math.cos(TWO_PI * (1 - D[1]))) * Dd[1];
  const exactObjective = D => 1.5 - D[0] * Math.cos(TWO_PI * D[1]) / TWO_PI;
  const exactGradient = D => [-Math.cos(TWO_PI * D[1]) / TWO_PI, D[0] * Math.sin(TWO_PI * D[1]), 0];
  /* the exact nodal values u*(x_j): the unknowns are point values, so there is no cell average on this page */
  const exactNodal = (x, D) => x.map(xj => ustar(xj, D));

  function make(opts) {
    const N = opts.N, kind = opts.kind || 'none', eps = opts.eps === undefined ? 0.01 : opts.eps;
    if (!Number.isInteger(N) || N < 4 || N > 4096) throw Error('viscous Burgers (nodes): N must be an integer in [4, 4096]');
    if (!['first', 'none', 'smooth'].includes(kind)) throw Error('viscous Burgers (nodes): the reconstruction is first, none or smooth');
    if (!(eps > 0)) throw Error('viscous Burgers (nodes): eps > 0');
    const h = 1 / N, M = N + 1, x = Array.from({length: M}, (_, j) => j * h), xf = Array.from({length: N}, (_, f) => (f + 0.5) * h);
    const W = x.map((_, j) => (j === 0 || j === N ? h / 2 : h)), w = x.map((xj, j) => W[j] * (1 + xj));
    const zeros = n => new Array(n).fill(0);
    const oneSided = kind !== 'first';   // the boundary nodes use the one-sided difference at second order, nothing at first order

    /* the slope of an interior node from its two one-sided differences m = U_j - U_{j-1}, p = U_{j+1} - U_j, and its partial derivatives */
    function sigma(m, p) {
      if (kind === 'first') return 0;
      if (kind === 'none') return 0.5 * (m + p);
      return m * p * (m + p) / (m * m + p * p + eps * eps);
    }
    function sigmaD(m, p) {
      if (kind === 'first') return [0, 0];
      if (kind === 'none') return [0.5, 0.5];
      const den = m * m + p * p + eps * eps, num = m * p * (m + p);
      return [((2 * m * p + p * p) * den - 2 * m * num) / (den * den), ((m * m + 2 * m * p) * den - 2 * p * num) / (den * den)];
    }
    const dist = () => h;

    /* ---------- statement 1-2 of the residual code: gather, reconstruct (slopes at the nodes), traces and flux of every face ---------- */
    function faces(U, D) {
      const nu = D[2], s = zeros(M), qL = zeros(N), qR = zeros(N), UL = zeros(N), UR = zeros(N), d = zeros(N), H = zeros(N);
      for (let j = 1; j < N; j++) s[j] = sigma(U[j] - U[j - 1], U[j + 1] - U[j]);
      s[0] = oneSided ? U[1] - U[0] : 0; s[N] = oneSided ? U[N] - U[N - 1] : 0;
      for (let f = 0; f < N; f++) {
        qL[f] = U[f] + 0.5 * s[f]; UL[f] = U[f]; qR[f] = U[f + 1] - 0.5 * s[f + 1]; UR[f] = U[f + 1]; d[f] = h;
        H[f] = 0.25 * (qL[f] * qL[f] + qR[f] * qR[f]) - (qR[f] - qL[f]) - nu * (UR[f] - UL[f]) / h;
      }
      return {s, qL, qR, UL, UR, d, H};
    }
    /* the exact integrated source of the dual volume j: Q_j - Q_{j-1} (zero entries at the two boundary nodes, whose rows are constraints) */
    const sourceRows = D => { const S = zeros(M); for (let j = 1; j < N; j++) S[j] = qstar(xf[j], D) - qstar(xf[j - 1], D); return S; };

    /* ---------- PRIMAL: the residual code ---------- */
    function residual(U, D) {
      const F = faces(U, D), S = sourceRows(D), R = zeros(M);
      for (let f = 0; f < N; f++) { if (f >= 1) R[f] += F.H[f]; if (f <= N - 2) R[f + 1] -= F.H[f]; }
      for (let j = 1; j < N; j++) R[j] -= S[j];
      R[0] = U[0] - uin(D); R[N] = U[N] - uout(D);
      return R;
    }
    const objective = U => U.reduce((acc, u, j) => acc + w[j] * u, 0);

    /* ---------- TANGENT: residual_d(U, Ud, D, Dd) = A Ud + R_D Dd, in the order of the primal code; tangentFaces returns every intermediate tangent ---------- */
    function tangentFaces(U, Ud, D, Dd) {
      const nu = D[2], nud = Dd[2], uind = uinD(D, Dd), uoutd = uoutD(D, Dd);
      const s = zeros(M), sd = zeros(M);
      for (let j = 1; j < N; j++) {
        const m = U[j] - U[j - 1], p = U[j + 1] - U[j], md = Ud[j] - Ud[j - 1], pd = Ud[j + 1] - Ud[j], g = sigmaD(m, p);
        s[j] = sigma(m, p); sd[j] = g[0] * md + g[1] * pd;
      }
      s[0] = oneSided ? U[1] - U[0] : 0; sd[0] = oneSided ? Ud[1] - Ud[0] : 0;
      s[N] = oneSided ? U[N] - U[N - 1] : 0; sd[N] = oneSided ? Ud[N] - Ud[N - 1] : 0;
      const T = {s, sd, qL: zeros(N), qLd: zeros(N), qR: zeros(N), qRd: zeros(N), UL: zeros(N), ULd: zeros(N), UR: zeros(N), URd: zeros(N),
        cL: zeros(N), cR: zeros(N), Hd: zeros(N), Qd: zeros(N), Sd: zeros(M), uind, uoutd};
      const Rd = zeros(M);
      for (let f = 0; f < N; f++) {
        const qL = U[f] + 0.5 * s[f], qLd = Ud[f] + 0.5 * sd[f], UL = U[f], ULd = Ud[f];
        const qR = U[f + 1] - 0.5 * s[f + 1], qRd = Ud[f + 1] - 0.5 * sd[f + 1], UR = U[f + 1], URd = Ud[f + 1];
        const cL = 0.5 * qL + 1, cR = 0.5 * qR - 1;
        const Hd = cL * qLd + cR * qRd - nu * (URd - ULd) / h - nud * (UR - UL) / h;
        T.qL[f] = qL; T.qLd[f] = qLd; T.qR[f] = qR; T.qRd[f] = qRd; T.UL[f] = UL; T.ULd[f] = ULd; T.UR[f] = UR; T.URd[f] = URd; T.cL[f] = cL; T.cR[f] = cR; T.Hd[f] = Hd;
        if (f >= 1) Rd[f] += Hd;
        if (f <= N - 2) Rd[f + 1] -= Hd;
      }
      for (let f = 0; f < N; f++) T.Qd[f] = qstarD(xf[f], D, Dd);
      for (let j = 1; j < N; j++) { T.Sd[j] = T.Qd[j] - T.Qd[j - 1]; Rd[j] -= T.Sd[j]; }
      Rd[0] = Ud[0] - uind; Rd[N] = Ud[N] - uoutd;
      T.Rd = Rd;
      return T;
    }
    const residualD = (U, Ud, D, Dd) => tangentFaces(U, Ud, D, Dd).Rd;

    /* ---------- REVERSE: residual_b(U, D, Rb) = (A^T Rb, R_D^T Rb), the statements of residual_d in reverse order, accumulating with += ---------- */
    function reverseFaces(U, D, Rb) {
      const nu = D[2], Ub = zeros(M), Db = [0, 0, 0];
      let uinb = 0, uoutb = 0;
      Ub[N] += Rb[N]; uoutb -= Rb[N]; Ub[0] += Rb[0]; uinb -= Rb[0];       // the constraint rows (the last primal statement runs first)
      const Qb = zeros(N);                                                  // the adjoint of Q_f: the statements R_j -= Q_j - Q_{j-1} run next in reverse
      for (let j = N - 1; j >= 1; j--) { Qb[j] -= Rb[j]; Qb[j - 1] += Rb[j]; }
      for (let f = N - 1; f >= 0; f--) qstarB(xf[f], D, Qb[f], Db);
      const s = zeros(M), sm = zeros(M), sp = zeros(M), sb = zeros(M);
      for (let j = 1; j < N; j++) { const m = U[j] - U[j - 1], p = U[j + 1] - U[j], g = sigmaD(m, p); s[j] = sigma(m, p); sm[j] = g[0]; sp[j] = g[1]; }
      s[0] = oneSided ? U[1] - U[0] : 0; s[N] = oneSided ? U[N] - U[N - 1] : 0;
      const B = {Qb, Hb: zeros(N), qLb: zeros(N), qRb: zeros(N), ULb: zeros(N), URb: zeros(N), sb, nub: zeros(N)};
      for (let f = N - 1; f >= 0; f--) {
        const qL = U[f] + 0.5 * s[f], UL = U[f], qR = U[f + 1] - 0.5 * s[f + 1], UR = U[f + 1];
        const Hb = (f >= 1 ? Rb[f] : 0) - (f <= N - 2 ? Rb[f + 1] : 0);
        const cL = 0.5 * qL + 1, cR = 0.5 * qR - 1, qLb = cL * Hb, qRb = cR * Hb, ULb = nu / h * Hb, URb = -nu / h * Hb;
        B.Hb[f] = Hb; B.qLb[f] = qLb; B.qRb[f] = qRb; B.ULb[f] = ULb; B.URb[f] = URb; B.nub[f] = -(UR - UL) / h * Hb;
        Db[2] += B.nub[f];
        Ub[f] += qLb + ULb; sb[f] += 0.5 * qLb;
        Ub[f + 1] += qRb + URb; sb[f + 1] += -0.5 * qRb;
      }
      for (let j = N - 1; j >= 1; j--) { const mb = sm[j] * sb[j], pb = sp[j] * sb[j]; Ub[j] += mb - pb; Ub[j - 1] += -mb; Ub[j + 1] += pb; }
      if (oneSided) { Ub[N] += sb[N]; Ub[N - 1] += -sb[N]; Ub[1] += sb[0]; Ub[0] += -sb[0]; }
      const zin = TWO_PI * (0 - D[1]), zout = TWO_PI * (1 - D[1]);
      Db[0] += Math.sin(zin) * uinb + Math.sin(zout) * uoutb;
      Db[1] += -TWO_PI * D[0] * (Math.cos(zin) * uinb + Math.cos(zout) * uoutb);
      B.Ub = Ub; B.Db = Db; B.uinb = uinb; B.uoutb = uoutb;
      return B;
    }
    const residualB = (U, D, Rb) => { const B = reverseFaces(U, D, Rb); return {Ub: B.Ub, Db: B.Db}; };

    /* ---------- the Jacobians by columns of the tangent code ---------- */
    function jacState(U, D) {
      const A = Array.from({length: M}, () => zeros(M)), z = [0, 0, 0];
      for (let j = 0; j < M; j++) { const e = zeros(M); e[j] = 1; const col = residualD(U, e, D, z); for (let i = 0; i < M; i++) A[i][j] = col[i]; }
      return A;
    }
    function jacDesign(U, D) {
      const z = zeros(M), cols = [0, 1, 2].map(k => residualD(U, z, D, [0, 1, 2].map(m => (m === k ? 1 : 0))));
      return Array.from({length: M}, (_, i) => [cols[0][i], cols[1][i], cols[2][i]]);
    }
    const transpose = A => A[0].map((_, j) => A.map(r => r[j]));
    const infnorm = v => v.reduce((m, z) => Math.max(m, Math.abs(z)), 0);

    /* ---------- the primal solve: Newton with a backtracking line search and the positive box 0.1 < U < 1.9 ---------- */
    function solve(D, o = {}) {
      let U = o.U0 ? o.U0.slice() : x.map(xj => ustar(xj, D));       // the exact nodal values: an initial guess only
      const history = [], states = [], tol = o.tol === undefined ? 1e-13 : o.tol, maxit = o.maxit || 35;
      for (let it = 0; it < maxit; it++) {
        const R = residual(U, D), A = jacState(U, D), dU = NUM.solve(NUM.factor(A), R.map(v => -v));
        const rn = infnorm(R), dn = infnorm(dU);
        history.push({iteration: it, residual: rn, correction: dn}); states.push(U.slice());
        if (dn <= tol || rn < 1e-15) return {U, history, states, converged: true};
        let step = 1, ok = false;
        for (let k = 0; k < 25; k++) {
          const T = U.map((u, i) => u + step * dU[i]);
          if (Math.min(...T) > 0.1 && Math.max(...T) < 1.9 && infnorm(residual(T, D)) < (1 - 1e-4 * step) * rn) { U = T; ok = true; break; }
          step *= 0.5;
        }
        if (!ok) return {U, history, states, converged: false, reason: 'line search failed'};
      }
      return {U, history, states, converged: false, reason: 'iteration limit'};
    }

    /* ---------- the tangent solves A v_k = -R_D e_k and the adjoint solve A^T psi = -g (g = w) ---------- */
    function sensitivities(U, D) {
      const A = jacState(U, D), RD = jacDesign(U, D), FA = NUM.factor(A), FAT = NUM.factor(transpose(A));
      const v = [0, 1, 2].map(k => NUM.solve(FA, RD.map(r => -r[k])));
      const psi = NUM.solve(FAT, w.map(z => -z));
      const gradTangent = v.map(vk => vk.reduce((acc, z, i) => acc + w[i] * z, 0));
      const gradAdjoint = [0, 1, 2].map(k => RD.reduce((acc, r, i) => acc + psi[i] * r[k], 0));
      return {A, RD, v, psi, gradTangent, gradAdjoint};
    }

    /* ---------- complex step: the SAME residual code with complex arithmetic (real and imaginary parts as two arrays); only the smooth operations the
       residual uses occur: + - * / and sin, cos of a complex argument ---------- */
    function residualComplex(Ure, Uim, Dre, Dim) {
      const C = {add: (a, b) => [a[0] + b[0], a[1] + b[1]], sub: (a, b) => [a[0] - b[0], a[1] - b[1]], mul: (a, b) => [a[0] * b[0] - a[1] * b[1], a[0] * b[1] + a[1] * b[0]],
        div: (a, b) => { const d = b[0] * b[0] + b[1] * b[1]; return [(a[0] * b[0] + a[1] * b[1]) / d, (a[1] * b[0] - a[0] * b[1]) / d]; },
        sc: (t, a) => [t * a[0], t * a[1]], k: t => [t, 0],
        sin: a => [Math.sin(a[0]) * Math.cosh(a[1]), Math.cos(a[0]) * Math.sinh(a[1])], cos: a => [Math.cos(a[0]) * Math.cosh(a[1]), -Math.sin(a[0]) * Math.sinh(a[1])]};
      const U = Ure.map((r, i) => [r, Uim[i]]), a = [Dre[0], Dim[0]], phi = [Dre[1], Dim[1]], nu = [Dre[2], Dim[2]];
      const ustarC = xx => C.add(C.k(1), C.mul(a, C.sin(C.sc(TWO_PI, C.sub(C.k(xx), phi)))));
      const qstarC = xx => { const z = C.sc(TWO_PI, C.sub(C.k(xx), phi)), u = C.add(C.k(1), C.mul(a, C.sin(z))), ux = C.mul(C.sc(TWO_PI, a), C.cos(z)); return C.sub(C.sc(0.5, C.mul(u, u)), C.mul(nu, ux)); };
      const sigmaC = (m, p) => {
        if (kind === 'first') return C.k(0);
        if (kind === 'none') return C.sc(0.5, C.add(m, p));
        return C.div(C.mul(C.mul(m, p), C.add(m, p)), C.add(C.add(C.mul(m, m), C.mul(p, p)), C.k(eps * eps)));
      };
      const s = Array.from({length: M}, () => C.k(0));
      for (let j = 1; j < N; j++) s[j] = sigmaC(C.sub(U[j], U[j - 1]), C.sub(U[j + 1], U[j]));
      if (oneSided) { s[0] = C.sub(U[1], U[0]); s[N] = C.sub(U[N], U[N - 1]); }
      const R = Array.from({length: M}, () => C.k(0));
      for (let f = 0; f < N; f++) {
        const qL = C.add(U[f], C.sc(0.5, s[f])), UL = U[f], qR = C.sub(U[f + 1], C.sc(0.5, s[f + 1])), UR = U[f + 1];
        const H = C.sub(C.sub(C.sc(0.25, C.add(C.mul(qL, qL), C.mul(qR, qR))), C.sub(qR, qL)), C.sc(1 / h, C.mul(nu, C.sub(UR, UL))));
        if (f >= 1) R[f] = C.add(R[f], H);
        if (f <= N - 2) R[f + 1] = C.sub(R[f + 1], H);
      }
      for (let j = 1; j < N; j++) R[j] = C.sub(R[j], C.sub(qstarC(xf[j]), qstarC(xf[j - 1])));
      R[0] = C.sub(U[0], ustarC(0)); R[N] = C.sub(U[N], ustarC(1));
      return {re: R.map(z => z[0]), im: R.map(z => z[1])};
    }

    return {N, M, h, kind, eps, x, xf, w, W, dist, sigma, sigmaD, faces, sourceRows, residual, residualD, residualB, tangentFaces, reverseFaces, objective, jacState, jacDesign, transpose, solve, sensitivities, residualComplex,
      exactNodal: D => exactNodal(x, D), exactAverage: D => exactNodal(x, D), infnorm};
  }

  /* ---------- the continuous adjoint, by an independent method: Chebyshev collocation of  -u lam' - nu lam'' = -(1 + x),  lam(0) = lam(1) = 0 ---------- */
  function continuousAdjoint(D, M = 200) {
    const xc = Array.from({length: M + 1}, (_, k) => Math.cos(Math.PI * k / M)), c = xc.map((_, k) => (k === 0 || k === M ? 2 : 1) * (k % 2 ? -1 : 1));
    const Dm = Array.from({length: M + 1}, () => new Array(M + 1).fill(0));
    for (let i = 0; i <= M; i++) { let row = 0; for (let j = 0; j <= M; j++) if (i !== j) { Dm[i][j] = (c[i] / c[j]) / (xc[i] - xc[j]); row += Dm[i][j]; } Dm[i][i] = -row; }
    const x = xc.map(z => (z + 1) / 2), d1 = Dm.map(r => r.map(z => 2 * z));
    const d2 = d1.map((r, i) => r.map((_, j) => r.reduce((acc, z, k) => acc + z * d1[k][j], 0)));
    const L = d1.map((r, i) => r.map((z, j) => -ustar(x[i], D) * z - D[2] * d2[i][j])), rhs = x.map(z => -(1 + z));
    for (const i of [0, M]) { L[i] = new Array(M + 1).fill(0); L[i][i] = 1; rhs[i] = 0; }
    const lam = NUM.solve(NUM.factor(L), rhs), lamX = d1.map(r => r.reduce((acc, z, j) => acc + z * lam[j], 0));
    /* barycentric interpolation of lam and lam_x at arbitrary points */
    const bw = xc.map((_, k) => (k === 0 || k === M ? 0.5 : 1) * (k % 2 ? -1 : 1));
    const interp = (f, z) => { let num = 0, den = 0; for (let k = 0; k <= M; k++) { const dz = z - x[k]; if (Math.abs(dz) < 1e-15) return f[k]; const t = bw[k] / dz; num += t * f[k]; den += t; } return num / den; };
    return {x, lam, lamX, at: z => interp(lam, z), atX: z => interp(lamX, z)};
  }

  const api = {make, ustar, ustarX, qstar, qstarD, uin, uout, exactObjective, exactGradient, exactNodal, exactAverage: (x, h, D) => exactNodal(x, D), continuousAdjoint, TWO_PI,
    DEFAULT_D: [0.2, 0.07, 0.01], DEFAULTS: {N: 8, kind: 'none'}};
  if (typeof module !== 'undefined') module.exports = api; else root.ViscousBurgers = api;
})(typeof window !== 'undefined' ? window : globalThis);