方程:可压缩 RANS 方程与 Spalart–Allmaras 模型
The equations: compressible RANS with the Spalart–Allmaras model
从守恒律到定常 RANS–SA 方程
From conservation laws to the steady RANS–SA equations
本页的方程描述可压缩气体绕物体的湍流。质量、动量、能量守恒给出 Navier–Stokes 方程;湍流在很小的尺度上快速脉动,工程计算只求平均流(雷诺平均,RANS)。平均后多出脉动造成的动量与热量输运(雷诺应力),方程不再封闭。涡粘性假设把它写成附加的粘度 μt,加到分子粘度上,并按湍流普朗特数 Prt 加到导热上;Spalart–Allmaras(SA)模型用工作变量 ν̃ 的一个输运方程给出 μt。于是每个点有 5 个未知量 (ρ, ρu, ρv, ρE, ρν̃),比二维层流 N–S 多一个。
The equations of this page describe turbulent flow of a compressible gas around a body. Conservation of mass, momentum and energy gives the Navier–Stokes equations; turbulence fluctuates rapidly on small scales, and engineering calculations solve for the mean flow only (Reynolds averaging, RANS). Averaging leaves an extra transport of momentum and heat by the fluctuations (the Reynolds stresses), and the equations are no longer closed. The eddy-viscosity hypothesis writes it as an added viscosity μt, added to the molecular one and, through a turbulent Prandtl number Prt, to the heat conduction; the Spalart–Allmaras (SA) model supplies μt through one transport equation for a working variable ν̃. Every point then carries 5 unknowns (ρ, ρu, ρv, ρE, ρν̃), one more than two-dimensional laminar N–S.
守恒形式的 RANS–SA 方程,带时间项:
RANS–SA in conservation form, with the time term:
本页要的是定常解:∂U/∂t = 0,于是 ∇·(Fc − Fv) = S。时间项仍然要写出来,因为定常解正是靠伪时间推进得到的:从初始状态出发沿 t 推进,直到时间导数消失(第 6 节)。这里的 t 是伪时间,每个控制体取自己的步长,所以推进的中间状态不是真实的时间历程,只有推进到底得到的定常解才有物理意义。
This page wants the steady solution: ∂U/∂t = 0, so that ∇·(Fc − Fv) = S. The time term is still written, because the steady solution is reached by pseudo-time marching: from an initial state, U is advanced in t until the time derivative vanishes (Section 6). Here t is a pseudo time and every control volume takes its own step, so the intermediate states are not a physical time history; only the steady solution the marching ends at has a physical meaning.
对流通量是 Euler 通量加上随质量通量走的 ρν̃;粘性通量是应力、热流与 SA 的扩散:
The convective flux is the Euler flux plus ρν̃ carried by the mass flux; the viscous flux holds the stress, the heat flux and the SA diffusion:
其中 (取 、、,所以 ),(Sutherland),湍流粘度 ,,
with (, , , so ), (Sutherland), the eddy viscosity with , and
、、。源项只在第 5 个方程里,是 NASA TMR 给出的 SA 守恒形式(密度梯度项不能丢):
, , . The source sits in the fifth equation only; it is the conservative form of the SA model given by NASA's TMR (the density-gradient term must not be dropped):
模型函数取标准(非负)版本:
The model functions are the standard (not the negative) version:
Ω = |∂v/∂x − ∂u/∂y| 是涡量的大小;常数 cb1 = 0.1355、cb2 = 0.622、κ = 0.41、cw2 = 0.3、cw3 = 2、cv1 = 7.1、ct3 = 1.2、ct4 = 0.5、c2 = 0.7、c3 = 0.9,cw1 = cb1/κ² + (1 + cb2)/σ。
Ω = |∂v/∂x − ∂u/∂y| is the size of the vorticity; the constants are cb1 = 0.1355, cb2 = 0.622, κ = 0.41, cw2 = 0.3, cw3 = 2, cv1 = 7.1, ct3 = 1.2, ct4 = 0.5, c2 = 0.7, c3 = 0.9, and cw1 = cb1/κ² + (1 + cb2)/σ.
模型、常数与守恒形式取自 Spalart 与 Allmaras(1994)、Allmaras、Johnson 与 Spalart(2012)以及 NASA 的湍流模型资源网站 TMR;第 3 节的 Roe 通量见 Roe(1981),粘性通量的修正平均梯度与格点页的边式格式见 SU2(Economon 等,2016)。书目列在附录 A 末尾。
The model, its constants and the conservative form follow Spalart and Allmaras (1994), Allmaras, Johnson and Spalart (2012) and NASA's Turbulence Modeling Resource (TMR); the Roe flux of Section 3 is Roe's (1981), and the corrected average gradient of the viscous flux and the node page's edge-based scheme are SU2's (Economon et al., 2016). The references are listed at the end of Appendix A.
这些函数各有来由。ν̃ 是 SA 的工作变量:离开壁面它就是涡粘性 νt = μt/ρ(fv1 → 1);靠近壁面 fv1 把它压低,νt = ν̃fv1(χ),于是 ν̃ 一直到壁面都随 d 线性变化,比 νt 容易算准。方程右端是生成减耗散:湍流由剪切产生,所以生成项与涡量 S̃ 成正比;壁面限制涡的尺度,所以耗散项按 (ν̃/d)² 增长。S̃ = Ω + ν̃fv2/(κ²d²) 在对数层里等于 uτ/(κd),fv2 让这一关系一直保持到壁面。r = ν̃/(S̃κ²d²) 比较湍流的长度尺度与壁面距离:对数层里 r = 1、fw = 1;离壁面越远 r 越大,fw 趋于常数 (1 + cw36)1/6 ≈ 2.0,所以把 r 截断在 10 并不改变模型,只免得 r6 溢出。ft2 的两项让 ν̃ = 0 成为一个稳定的解,层流区因此不会自己转捩。χ 略大于 1 时 fv2 变负,B 随之为负,Ω + B 可能小于零;2012 年的修正在 B < −c2Ω 时换成第二个式子,它与第一支在 B = −c2Ω 处值与一阶导数都相接,并让 S̃ 始终大于 0.1Ω。
Each of these functions has a purpose. ν̃ is SA's working variable: away from walls it is the eddy viscosity νt = μt/ρ (fv1 → 1); near a wall fv1 damps it, νt = ν̃fv1(χ), so that ν̃ varies linearly with d all the way to the wall and is easier to compute accurately than νt. The right-hand side is production minus destruction: turbulence is produced by shear, so production is proportional to the vorticity S̃; the wall limits the size of the eddies, so destruction grows as (ν̃/d)². S̃ = Ω + ν̃fv2/(κ²d²) equals uτ/(κd) in the log layer, and fv2 keeps that relation all the way to the wall. r = ν̃/(S̃κ²d²) compares the turbulent length scale with the wall distance: r = 1 and fw = 1 in the log layer; further from the wall r grows and fw tends to the constant (1 + cw36)1/6 ≈ 2.0, so capping r at 10 does not change the model and only keeps r6 from overflowing. The two ft2 terms make ν̃ = 0 a stable solution, so a laminar region does not turn turbulent by itself. For χ slightly above 1, fv2 turns negative, B with it, and Ω + B can drop below zero; the 2012 modification switches to the second expression for B < −c2Ω, which meets the first branch at B = −c2Ω in value and first derivative and keeps S̃ above 0.1Ω.
波速与边界条件
Wave speeds and boundary conditions
对流部分决定信息怎样传播。沿单位法向 n,对流通量 Jacobian 的五个特征值是两道声波 q ∓ c(c 是声速),以及都以 q = u·n 移动的熵波、剪切波和 ν̃ 波;本页 M = 0.2,处处亚声速。n 指向区域外时,特征值为负的波从外面进来;无粘极限下,边界上能给定几个值就看进来几道波:来流(q < 0)四道,出口(q > 0)一道。粘性项还要一些条件:来流给定 ρ、u、v、ν̃,T 自由、热流为零;出口给定牵引力 p n − τ·n = p∞n,热流与 ν̃ 的扩散通量为零;物面无滑移、绝热,ν̃ = 0。第 4 节的图 4.2 逐个边界数这些条件,同一节写出它们的离散。
The convective part decides how information travels. Along a unit normal n the five eigenvalues of the convective flux Jacobian are the acoustic waves q ∓ c (c the speed of sound) and the entropy, shear and ν̃ waves, all three at q = u·n; at M = 0.2 the flow is subsonic everywhere. With n pointing out of the domain, a wave with a negative eigenvalue comes in, and in the inviscid limit a boundary takes as many values as waves come in: four at the inflow (q < 0), one at the outlet (q > 0). The viscous terms need a few more: the inflow gives ρ, u, v and ν̃, with T free and zero heat flux; the outlet gives the traction p n − τ·n = p∞n and zero heat and ν̃ diffusive fluxes; the body is no-slip and adiabatic, with ν̃ = 0. Figure 4.2 counts these conditions boundary by boundary, and Section 4 writes out their discretisation.
四个 RANS–SA 页面解同一个连续问题:格心、格点两种控制体,各有两种来流边界的离散;同一种控制体的两个页面只在来流边界的离散上不同。本页用伴随一致的处理:来流节点保留质量行,只以节点自己的 ρ 固定 u、v、ν̃;原来的处理里,来流节点的 ρ、ρu、ρv、ρν̃ 四行换成 U − U∞。两者都给出各自离散问题的精确导数;区别在于加密时离散伴随在来流附近是否趋于连续伴随(伴随一致性)。做法见第 4 节,原因与逐级比较见附录 B。
The four RANS–SA pages solve the same continuous problem: two kinds of control volume, each with two discretisations of the inflow boundary; the two pages of one kind differ only in the inflow discretisation. This page uses the adjoint-consistent treatment: an inflow node keeps its mass row and fixes u, v and ν̃ at its own ρ; in the original treatment the ρ, ρu, ρv and ρν̃ rows of an inflow node are replaced by U − U∞. Both give the exact derivatives of their own discrete problems; they differ in whether, under refinement, the discrete adjoint approaches the continuous one near the inflow (adjoint consistency). Section 4 gives the two treatments, Appendix B the reason and a level-by-level comparison.
本页的问题
The problem on this page
区域是物体与远场之间的环:物体是凸八边形(弦长 1.1),远场是半径 1.9 的正八边形,第 2 节的网格填满两者之间。来流取 ρ∞ = T∞ = p∞ = 1,于是声速 c∞ = √γ,U∞ = M√γ。按伴随优化文献的通常写法,设计变量记作 D = (α, M, μref, X),共 51 个,X 是 24 个节点的 48 个坐标;目标函数是第 7 节的阻力系数 CD(下标 D 指阻力,不是设计变量)。基线解是页首默认设置(二阶)下 R(U) = 0 的收敛解(第 6 节),CD = 50.9985,这张粗网格上的阻力有多准见第 7 节。图 1.1 把这些画在一起。
The domain is the ring between the body, a convex octagon (chord 1.1), and the far field, a regular octagon of radius 1.9; the mesh of Section 2 fills it. The free stream has ρ∞ = T∞ = p∞ = 1, so c∞ = √γ and U∞ = M√γ. As is usual in the adjoint-optimization literature, the design variables are written D = (α, M, μref, X), 51 in all, with X the 48 coordinates of the 24 nodes; the objective is the drag coefficient CD of Section 7 (the subscript D stands for drag, not for the design). The baseline is the converged solution of R(U) = 0 at the header's default settings (second order; Section 6), with CD = 50.9985; Section 7 discusses how accurate the drag of this coarse mesh is. Figure 1.1 draws all of this.
本页的流动:M = 0.2,迎角 5°,μref = 0.02(以物体弦长 1.1 计 Re ≈ 13),来流 ν̃∞ = 3ν∞。出口是牵引力出口,定常尾迹必须顺着出口流出、不能倒流:第 4 级网格上出口的 u·n 最小为 0.07U∞,处处向外。整个区域绝热(壁面、来流、出口都没有热流),粘性加热只能随出口的流动带走,所以温度整体高于来流的 T∞ = 1:第 4 级网格上 T 在 [1.049, 1.099] 之间(来流面上 T 不给定,热也会向上游传到那里)。这样的网格分辨不了真实的高雷诺数边界层;这里要的是一个用得到模型各个分支、又能收敛到舍入误差的离散问题:r 的截断(S̃ 的修正分支在本页只出现在 ν̃ 行被替换的来流节点上,残差用不到它;第 4 节列出两者的控制体数),以及涡粘性:来流状态 χ = 3,μt/μ = 0.21;本页(第 0 级网格)各控制体上 μt/μ 最大 0.063(χ 最大 2.19):χ = ν̃/ν,ν = μ/ρ;区域里 ν̃ 不超过来流值,而 ν 处处至少是来流的 1.23 倍,所以 χ 比来流小。
The flow on this page: M = 0.2, 5° angle of attack, μref = 0.02 (Re ≈ 13 on the body's chord of 1.1), and ν̃∞ = 3ν∞ at the inflow. The outlet is a traction outlet, and the steady wake must leave through it without flowing back: on level 4 the outlet's smallest u·n is 0.07U∞, outward everywhere. The whole domain is adiabatic (no heat flux through the wall, the inflow or the outlet), so the viscous heating can only leave with the outflow, and the temperature lies above the free stream's T∞ = 1 throughout: on level 4, T is between 1.049 and 1.099 (T is not prescribed on the inflow faces, and heat reaches them upstream too). A mesh like this cannot resolve a real high-Reynolds boundary layer; the aim is a discrete problem that exercises the branches of the model and still converges to round-off: the cap on r (on this page the modified branch of S̃ occurs only at inflow nodes, whose ν̃ rows are replaced, so the residual does not use it; Section 4 counts the control volumes of both), and the eddy viscosity: at the inflow state χ = 3 and μt/μ = 0.21; over the control volumes of this page (the level-0 mesh) μt/μ is at most 0.063 (χ at most 2.19): χ = ν̃/ν with ν = μ/ρ, and inside the domain ν̃ does not exceed its inflow value while ν is everywhere at least 1.23 times the inflow's, so χ stays below the inflow's.
这组方程的作用
What these equations are for
在流体力学里,RANS 加一个湍流模型是计算飞机、叶轮机械等高雷诺数定常流动的常用办法:不解析每一个涡,只算平均流,一次计算就给出升力、阻力与压力分布。SA 模型最初为航空外流设计,只多一个输运方程,工程上用得很广。与层流 N–S 相比,湍流模型带来三样东西:多一个未知量和方程;涡粘性 μt = ρν̃fv1(χ) 进入动量与能量方程的粘性通量;依赖壁面距离 d 的源项,而 d 是网格坐标的函数。图 1.2 画出 fv1 怎样把 ν̃ 变成涡粘性。
In fluid dynamics, RANS with a turbulence model is the usual way to compute steady high-Reynolds-number flows around aircraft, turbomachinery and the like: it resolves no individual eddy, only the mean flow, and one calculation gives the lift, the drag and the pressure distribution. The SA model was designed for aerodynamic external flows; it adds one transport equation and is widely used in engineering. Compared with laminar N–S the turbulence model brings three things: one more unknown and equation; the eddy viscosity μt = ρν̃fv1(χ) in the viscous fluxes of momentum and energy; and source terms depending on the wall distance d, a function of the mesh coordinates. Figure 1.2 shows how fv1 turns ν̃ into an eddy viscosity.
在本课程里,二维非结构网格上 RANS–SA 的前向与伴随是整个系列的目标。用于气动外形优化的工业伴随求解器求的正是这类方程组:一次伴随求解给出阻力这样一个目标对成百上千个外形参数的导数。前面各页一次加一样东西,本页把它们合在一起(图 1.3)。本页的前向与伴随对五个方程一起求导,涡粘性对 ν̃ 的依赖、SA 源项与壁面距离都在其中;有些工程代码冻结湍流量、只对平均流方程求伴随,本页不做这种近似。
In this course, the tangent and the adjoint of RANS–SA on a two-dimensional unstructured mesh are the goal of the whole series. Industrial adjoint solvers for aerodynamic shape optimisation solve exactly this kind of system: one adjoint solve gives the derivative of one objective, such as the drag, with respect to hundreds or thousands of shape parameters. The earlier pages add one ingredient at a time; this page puts them together (Figure 1.3). Its tangent and adjoint differentiate all five equations together, including the eddy viscosity's dependence on ν̃, the SA source and the wall distance; some production codes freeze the turbulence quantities and take the adjoint of the mean-flow equations only, and this page makes no such approximation.
本页要回答的问题
The question this page answers
本页只回答一个问题:51 个设计变量 D 各改变一点,CD 改变多少?页首的全页路线图把后面各节串成一条线:前向每个设计变量解一次线性方程,共 51 次;伴随只解一次转置方程。
This page answers one question: how much does CD change when each of the 51 design variables D changes a little? The page roadmap at the top strings the later sections together: the tangent solves one linear system per design variable, 51 in all, the adjoint a single transposed one.
要在计算机上回答它,先要把上面的偏微分方程变成有限个未知量的代数方程 R(U) = 0。第 2 节放下网格与控制体,第 3 节再把每个控制体上的守恒写成面通量之和:Roe 通量、最小二乘重构、粘性通量与 SA 源项。
To answer it on a computer, the partial differential equations above must first become algebraic equations R(U) = 0 in finitely many unknowns. Section 2 lays out the mesh and the control volumes, and Section 3 writes conservation on each as a sum of face fluxes: the Roe flux, the least-squares reconstruction, the viscous flux and the SA source.
网格:对偶控制体、对偶面与壁面距离
Mesh: dual control volumes, dual faces and wall distance
第 1 节的方程在区域里每一点成立,计算机却只能存有限个数。本节决定未知量放在哪里:网格、控制体与它们的几何量,包括 SA 源项要用的壁面距离。
The equations of Section 1 hold at every point of the domain, but a computer stores finitely many numbers. This section decides where the unknowns live: the mesh, the control volumes and their geometry, including the wall distance the SA source needs.
网格与二维对流页面完全相同,编号也相同:节点逐圈从壁面向外,单元逐圈编号,面按“内部、壁面、远场”排序。未知量放在节点上:每个节点的控制体是中位对偶,由相邻单元的边中点与单元中心围成。区别在于每个控制体现在有 5 个未知量,而不是 1 个。
The mesh is exactly that of the two-dimensional advection page, with the same numbering: nodes ring by ring from the wall outwards, cells ring by ring, faces sorted interior, wall, far field. The unknowns live at the nodes: each node's control volume is its median dual, bounded by the edge midpoints and the centres of the cells around it. The difference is that every control volume now carries 5 unknowns instead of 1.
一个面循环要读的几何量都画在下图里。和标量页面相比多了两样:从控制体中心 xi 到面点 xf 的重构方向 xf − xi(二阶格式沿它把中心值外推到面上),与两侧中心的连线 Δx = xR − xL(粘性通量沿它取两点差分)。
The geometric quantities a face loop reads are all in the figure below. Compared with the scalar pages there are two more: the reconstruction direction xf − xi from a control-volume centre xi to the face point xf (the second-order scheme extrapolates the centre value along it), and the line Δx = xR − xL between the two centres (the viscous flux takes its two-point difference along it).
壁面距离
The wall distance
SA 模型的耗散项与 (ν̃/d)² 成正比,d 是到壁面的距离。本页的 di 是控制体中心到离散壁面多边形的精确欧氏距离:对每条壁面边求点到线段的距离,取最小。它是坐标的函数,所以在第 12 节的几何导数里也要求导。
The SA model's destruction term goes as (ν̃/d)², with d the distance to the wall. On this page di is the exact Euclidean distance from the control-volume centre to the discrete wall polygon: the distance from the point to each wall edge, and the smallest. It is a function of the coordinates, so the geometric derivatives of Section 12 differentiate it too.
逐步推导:壁面距离与它对坐标的导数
Step by step: the wall distance and its derivative with respect to the coordinates
第 12 节的几何导数要用到 ∂di/∂X。di 是分段定义的:最近点可能落在一条壁面边的内部,也可能落在顶点上。先把它写成显式公式,再逐项求导。记控制体中心为 xi,一条壁面边从壁面节点 Xa 到 Xb,e = Xb − Xa。
The geometric derivatives of Section 12 need ∂di/∂X. di is defined piecewise: the nearest point may lie inside a wall edge or at a vertex. Write it as an explicit formula first, then differentiate term by term. Let xi be the control-volume centre and let a wall edge run from the wall node Xa to Xb, with e = Xb − Xa.
第一步,直线上的最近点。直线上的点是 Xa + ξe;到 xi 的距离平方对 ξ 求导并令其为零:
Step 1, the nearest point on the line. The points of the line are Xa + ξe; differentiate the squared distance to xi with respect to ξ and set it to zero:
第二步,截到线段上。ξ* ≤ 0 时最近点是顶点 Xa,ξ* ≥ 1 时是 Xb,否则是垂足。记截断后的参数 ξ = min(max(ξ*, 0), 1),最近点 xw = Xa + ξe,距离与它的单位方向是
Step 2, clamp to the segment. For ξ* ≤ 0 the nearest point is the vertex Xa, for ξ* ≥ 1 it is Xb, and otherwise the foot of the perpendicular. With the clamped parameter ξ = min(max(ξ*, 0), 1) the nearest point is xw = Xa + ξe, and the distance and its unit direction are
di 取所有壁面边中最小的那个(mesh.js 的 segDist 与 geometry 正是这样算的,分支都按实数值选)。
di is the smallest over all wall edges (mesh.js segDist and geometry compute exactly this, every branch chosen on real values).
第三步,垂足情形求导。d² = |xi − Xa − ξe|²,而 ξ = ξ*(xi, Xa, Xb) 本身也随坐标变。但 ξ* 使这个距离平方取极小,∂(d²)/∂ξ = 0:ξ 的变化对 d 没有一阶影响(包络定理)。所以只对显式出现的三个点求前向导数(图 2.4 (a)):
Step 3, differentiate in the foot case. d² = |xi − Xa − ξe|², and ξ = ξ*(xi, Xa, Xb) moves with the coordinates as well. But ξ* minimises this squared distance, so ∂(d²)/∂ξ = 0: a change of ξ has no first-order effect on d (the envelope theorem). Only the three points that appear explicitly are differentiated, in forward mode (Figure 2.4 (a)):
nw 与 e 垂直,所以沿壁面边移动 Xa 或 Xb 不改变 d;三个导数之和为零,整体平移不改变 d。
nw is perpendicular to e, so moving Xa or Xb along the edge leaves d unchanged; the three derivatives sum to zero, and a rigid translation does not change d.
第四步,顶点情形。ξ* ≤ 0 时 d = |xi − Xa|,直接求导得 ∂d/∂xi = nw、∂d/∂Xa = −nw、∂d/∂Xb = 0:正是第三步的公式取 ξ = 0(ξ* ≥ 1 时取 ξ = 1)。一个公式覆盖两种情形;在 ξ* = 0 处两边的值与导数都相同,所以最近点从顶点滑进边内时,d 的导数不跳。
Step 4, the vertex case. For ξ* ≤ 0, d = |xi − Xa|, and direct differentiation gives ∂d/∂xi = nw, ∂d/∂Xa = −nw, ∂d/∂Xb = 0: Step 3's formula with ξ = 0 (and ξ = 1 for ξ* ≥ 1). One formula covers both cases; at ξ* = 0 both sides have the same value and the same derivative, so the derivative of d does not jump when the nearest point slides from the vertex into the edge.
第五步,回到节点坐标。格点页的中心就是节点本身,xi = Xi,所以 ∂di/∂Xi = nw;Xa、Xb 是壁面节点,各得到第三步的一项。壁面节点自己的 d = 0,不求源项,也不求导。
Step 5, back to the node coordinates. On the node page the centre is the node itself, xi = Xi, so ∂di/∂Xi = nw; Xa and Xb are wall nodes and receive the terms of Step 3. A wall node's own d = 0: it has no source and no derivative.
核对:本页 16 个中心里,2 个的最近点在边内,14 个在顶点上;对每个 di,第三至第五步的公式与 geometry() 的磁带反向扫描给出的 ∂di/∂X 最大相对差 4.6×10−16(本页代码在构建时计算)。
Check: of this page's 16 centres, 2 have their nearest point inside an edge and 14 at a vertex; for every di, the formulas of Steps 3 to 5 and a reverse sweep of a tape of geometry() give ∂di/∂X with a largest relative difference of 4.6×10−16 (computed by this page's code at build time).
网格与几何量到这里就齐了。第 3 节把第 1 节的守恒律对每个控制体积分,写成穿过这些面的通量之和。
The mesh and its geometry are now complete. Section 3 integrates the conservation laws of Section 1 over each control volume and writes them as sums of fluxes through these faces.
面上的通量
The flux on a face
第 2 节给出了控制体和它们的面。本节把第 1 节的方程对每个控制体积分,写出每个面上的通量:Roe 通量、最小二乘重构、粘性通量,以及每个控制体的 SA 源项。
Section 2 gave the control volumes and their faces. This section integrates the equations of Section 1 over each control volume and writes the flux through each face: the Roe flux, the least-squares reconstruction, the viscous flux, and each control volume's SA source.
有限体积形式
The finite-volume form
对每个控制体积分(Ui 取控制体上的平均值),散度变成面上的通量和,每个控制体得到一个关于 t 的常微分方程(半离散形式):
Integrated over each control volume (Ui is the average over it), the divergence becomes a sum of face fluxes, and each control volume gets an ordinary differential equation in t (the semi-discrete form):
roe 是对流部分,visc 是粘性部分。面通量 Φf 从 L 流向 R:对 L 加、对 R 减,保证守恒。W = (ρ, u, v, T, ν̃) 是原始变量,G 是它们的最小二乘梯度,W+ 是重构到面上的状态。
roe is the convective part and visc the viscous one. The face flux Φf runs from L to R: added to L and subtracted from R, which makes the scheme conservative. W = (ρ, u, v, T, ν̃) are the primitive variables, G their least-squares gradients, and W+ the state reconstructed to the face.
定常解满足 R(U) = 0:这就是本页要解、并在之后各节求导的离散方程;时间项只在求解时出现(第 6 节)。格点页壁面节点的 ρu、ρv、ρν̃ 三行与来流节点的 ρu、ρv、ρν̃ 三行不是上面的常微分方程:它们被替换成边界条件本身(第 4 节),推进中始终精确满足壁面上 u = v = ν̃ = 0、来流节点上 u、v、ν̃ 等于来流值;来流节点的 ρ 仍由它的质量守恒决定。
The steady solution satisfies R(U) = 0: that is the discrete equation this page solves and, in the later sections, differentiates; the time term appears in the solve only (Section 6). The ρu, ρv and ρν̃ rows of a wall node and the ρu, ρv and ρν̃ rows of an inflow node are not ODEs like the one above: they are replaced by the boundary conditions themselves (Section 4), and u = v = ν̃ = 0 on the wall and the inflow values of u, v, ν̃ on the inflow nodes hold exactly throughout the marching; an inflow node's ρ is still set by its mass balance.
每个面仍是一个一维问题:Roe 通量
Every face is still a one-dimensional problem: the Roe flux
面的两侧各有一个状态,Roe 通量把它们的差分解成五道波:两道声波(速度 q̃ ∓ c̃)、熵波、剪切波与 ν̃ 波(速度都是 q̃),每道波按它速度的绝对值加耗散:
Each side of a face carries a state, and the Roe flux splits their difference into five waves: two acoustic waves (speeds q̃ ∓ c̃), and the entropy, shear and ν̃ waves (all at speed q̃); each wave is dissipated in proportion to the size of its speed:
~ 表示 Roe 平均(以 √ρ 加权:ρ̃ = √(ρLρR),ũ、H̃、ν̃~ 是两侧的加权平均),c̃² = (γ − 1)(H̃ − ½|ũ|²),q̃ = ũ·n̂。Δ 表示 R 侧减 L 侧的跳跃,Δq = Δu·n̂。Λk 是第 k 道波的波速,rk 是 Roe 平均状态处通量 Jacobian 的右特征向量(分量按 ρ、ρu、ρv、ρE、ρν̃ 排列),Δk 是波强:把跳跃 ΔU 写成 ΣkΔkrk 时的系数。
The ~ marks a Roe average (weighted by √ρ: ρ̃ = √(ρLρR), and ũ, H̃, ν̃~ are the weighted averages of the two sides), c̃² = (γ − 1)(H̃ − ½|ũ|²) and q̃ = ũ·n̂. Δ is a jump, the R side minus the L side, and Δq = Δu·n̂. Λk is the speed of wave k, rk the right eigenvector of the flux Jacobian at the Roe-averaged state (components ordered ρ, ρu, ρv, ρE, ρν̃), and Δk the wave strength: the coefficient of rk when the jump ΔU is written as ΣkΔkrk.
两道声波(k = 1、3)、熵波(k = 2)、剪切波(k = 4)与 ν̃ 波(k = 5);后三道都以 q̃ 移动。剪切波与 ν̃ 波直接写成乘积 Δkrk。ρν̃ 作为被动标量跟着质量通量走:r1,2,3 的最后一个分量是 ν̃~,所以它的耗散是 ν̃~ 乘质量方程的耗散,再加 ν̃ 波的 |q̃|ρ̃Δν̃。残差里的特征值不做熵修正:熵修正是为了在声速点(|q̃ ± c̃| → 0)附近防止出现非物理的膨胀激波,本页 M = 0.2,处处亚声速,用不到它。代价是 |Λk|(k = 2, 4, 5)在 q̃ = 0 处不可导(第 4 节列出它离当前解多远)。
The two acoustic waves (k = 1, 3), the entropy wave (k = 2), the shear wave (k = 4) and the ν̃ wave (k = 5); the last three all move at q̃. The shear and ν̃ waves are written directly as the products Δkrk. ρν̃ rides on the mass flux as a passive scalar: the last component of r1,2,3 is ν̃~, so its dissipation is ν̃~ times the mass equation's, plus the ν̃ wave's |q̃|ρ̃Δν̃. The residual's eigenvalues carry no entropy fix: an entropy fix keeps non-physical expansion shocks from forming near sonic points (|q̃ ± c̃| → 0), and this page's flow at M = 0.2 is subsonic everywhere. The price is that |Λk| (k = 2, 4, 5) is not differentiable at q̃ = 0 (Section 4 lists how far the solution is from it).
逐步推导:Roe 平均、波分解与 Roe 通量的线性化
Step by step: Roe averages, the wave decomposition and the linearisation of the Roe flux
第一步,Roe 平均的乘积法则。任一量 φ 的 Roe 平均是 φ̃ = (√ρLφL + √ρRφR)/(√ρL + √ρR),ρ̃ = √(ρLρR)。直接展开(用 ρR − ρL = (√ρR − √ρL)(√ρR + √ρL)):
Step 1, the product rule of Roe averages. The Roe average of any quantity φ is φ̃ = (√ρLφL + √ρRφR)/(√ρL + √ρR), and ρ̃ = √(ρLρR). Expanding directly (with ρR − ρL = (√ρR − √ρL)(√ρR + √ρL)):
所以对 φ = u、v、H、ν̃,跳跃 Δ(ρφ) 精确地等于 φ̃Δρ + ρ̃Δφ:在 Roe 平均处把跳跃线性化没有误差。
So for φ = u, v, H, ν̃ the jump Δ(ρφ) is exactly φ̃Δρ + ρ̃Δφ: linearising the jump at the Roe average makes no error.
第二步,压力的跳跃。本页 p = ρT、ρE = ρ(cvT + ½|u|²),所以 p = (γ − 1)(ρE − ½ρ|u|²)。写 ρ|u|² = |√ρ u|²,并用 √ρLuL + √ρRuR = (√ρL + √ρR)ũ,得 ½Δ(ρ|u|²) = ũ·Δ(ρu) − ½|ũ|²Δρ,于是
Step 2, the pressure jump. On this page p = ρT and ρE = ρ(cvT + ½|u|²), so p = (γ − 1)(ρE − ½ρ|u|²). Writing ρ|u|² = |√ρ u|² and using √ρLuL + √ρRuR = (√ρL + √ρR)ũ gives ½Δ(ρ|u|²) = ũ·Δ(ρu) − ½|ũ|²Δρ, hence
第三步,求波强。把跳跃写成 ΔU = ΣkΔkrk,逐个分量比较(rk 见上式)。质量分量:Δ1 + Δ2 + Δ3 = Δρ。法向动量 n̂·Δ(ρu) = q̃Δρ + ρ̃Δq:c̃(Δ3 − Δ1) = ρ̃Δq。把第二步 Δp 的式子(γ − 1 乘方括号)作用在每个 rk 上,r1、r3 给 c̃²,r2 与剪切、ν̃ 两个向量给 0,所以 c̃²(Δ1 + Δ3) = Δp。三式联立:
Step 3, the wave strengths. Write the jump as ΔU = ΣkΔkrk and compare component by component (the rk as above). The mass component: Δ1 + Δ2 + Δ3 = Δρ. The normal momentum n̂·Δ(ρu) = q̃Δρ + ρ̃Δq: c̃(Δ3 − Δ1) = ρ̃Δq. Step 2's formula for Δp ((γ − 1) times the bracket) applied to each rk gives c̃² for r1 and r3 and 0 for r2 and the shear and ν̃ vectors, so c̃²(Δ1 + Δ3) = Δp. Together:
动量里剩下的 ρ̃(Δu − Δq n̂) 是剪切波;ρν̃ 里剩下的 ρ̃Δν̃(第一步取 φ = ν̃)是 ν̃ 波:正是上面的 Δ4r4、Δ5r5。
What remains in the momentum, ρ̃(Δu − Δq n̂), is the shear wave; what remains in ρν̃, ρ̃Δν̃ (Step 1 with φ = ν̃), is the ν̃ wave: the Δ4r4 and Δ5r5 above.
第四步,耗散矩阵。rk 是 Roe 平均状态处通量 Jacobian 的特征向量,特征值 Λk。把跳跃按特征向量展开、逐波乘 |Λk|,就是 |J̃c|ΔU。记 𝓡 = (r1, …, r5):
Step 4, the dissipation matrix. The rk are the eigenvectors of the flux Jacobian at the Roe-averaged state, with eigenvalues Λk. Expanding the jump in eigenvectors and multiplying each wave by |Λk| gives |J̃c|ΔU. With 𝓡 = (r1, …, r5):
第二式来自 r1、r2、r3 的最后一个分量都是 ν̃~、剪切波的是 0(model.js 的 d4 = st·d0 + sh·ds)。所以 |J̃c| 的 ρν̃ 列只有对角元 |q̃|:ν̃ 不进入平均流方程的耗散,而 ρν̃ 的耗散是质量耗散乘 ν̃~ 再加自己的一项。本页一个面上的 |J̃c| 见图 3.2。
The second formula holds because the last component of r1, r2 and r3 is ν̃~ and that of the shear wave is 0 (model.js's d4 = st·d0 + sh·ds). So the ρν̃ column of |J̃c| holds only the diagonal |q̃|: ν̃ does not enter the mean-flow equations' dissipation, and ρν̃'s dissipation is the mass dissipation times ν̃~ plus a term of its own. Figure 3.2 shows |J̃c| on one face of this page.
第五步,线性化。一阶格式 Φ = |n|[½(F(UL) + F(UR))·n̂ − ½|J̃c|ΔU],而 J̃c 同时依赖两侧状态,所以
Step 5, the linearisation. At first order Φ = |n|[½(F(UL) + F(UR))·n̂ − ½|J̃c|ΔU], and J̃c depends on both states, so
最后一项与跳跃 ΔU 成正比,含 |Λk| 的导数 sgn Λk(Λk = 0 处不可导,第 4 节列出了余量)。局部磁带对核的每个运算求导,三项全部精确算到;第 6 节的近似 Jacobian 只留前两项。二阶格式的面状态是 WL+ = WL + GL·(xf − xL),所以 Roe 部分对 WL 的导数等于它对 WL+ 的导数,对 GL 的导数是它再乘 (xf − xL)T;粘性通量另外直接读 WL、WR 与 GL、GR,所以面核在两种格式里都有这 30 个输入。
The last term is proportional to the jump ΔU and contains the derivative of |Λk|, sgn Λk (not differentiable at Λk = 0; Section 4 lists the margins). The local tape differentiates every operation of the kernel, so all three terms come out exactly; the approximate Jacobian of Section 6 keeps only the first two. At second order the face state is WL+ = WL + GL·(xf − xL), so the Roe part's derivative with respect to WL equals its derivative with respect to WL+, and with respect to GL it is that times (xf − xL)T; the viscous flux reads WL, WR and GL, GR directly as well, which is why the face kernel has these 30 inputs at either order.
核对:本页全部 48 个内部面上(U* 处的二阶面状态),Jc(W̃)rk = Λkrk 的相对残差最大 2.5×10−16;ΣkΔkrk 重建跳跃 ΔU 到 2.8×10−14;𝓡|Λ|𝓡−1ΔU 与 model.js 的耗散相差 1.8×10−14;Roe 性质 F(UR) − F(UL) = Jc(W̃)ΔU 成立到 8.4×10−15;|J̃c| 的 ρν̃ 行与列符合第四步到 3.2×10−18。第五步被丢掉的最后一项(一阶、中心状态)占磁带给出的 ∂Φ/∂UL 的比例(Frobenius 范数):最大 25.1%,中位数 8.8%(本页代码在构建时计算)。
Check: on all 48 interior faces of this page (the second-order face states at U*), Jc(W̃)rk = Λkrk holds to a relative residual of at most 2.5×10−16; ΣkΔkrk rebuilds the jump ΔU to 2.8×10−14; 𝓡|Λ|𝓡−1ΔU agrees with model.js's dissipation to 1.8×10−14; Roe's property F(UR) − F(UL) = Jc(W̃)ΔU holds to 8.4×10−15; and the ρν̃ row and column of |J̃c| follow Step 4 to 3.2×10−18. The last term dropped in Step 5 (first order, centre states) is at most 25.1% of the taped ∂Φ/∂UL (Frobenius norm), 8.8% at the median (computed by this page's code at build time).
第二步的恒等式与第三步的分解另由 sympy 符号验证(check_enrich_sympy.py)。
The identity of Step 2 and the decomposition of Step 3 are also verified symbolically by sympy (check_enrich_sympy.py).
最小二乘重构:一阶与二阶
Least-squares reconstruction: first and second order
每个控制体的梯度来自无权最小二乘:
Each control volume's gradient comes from unweighted least squares:
模板是边相邻的节点。壁面节点本身就是未知量(强条件下 u = v = ν̃ = 0),所以不需要额外的壁面点。二阶格式把中心值沿 xf − xi 外推:W+ = Wi + Gi·(xf − xi),不加限制器(流动无激波);一阶格式直接取 W+ = Wi。粘性通量与 SA 源项在两种格式里都用这些梯度,所以一阶/二阶开关只改变对流通量。
The stencil is the edge neighbours. A wall node is itself an unknown (u = v = ν̃ = 0 under the strong condition), so no extra wall point is needed. The second-order scheme extrapolates the centre value along xf − xi: W+ = Wi + Gi·(xf − xi), without a limiter (the flow has no shocks); the first-order scheme takes W+ = Wi. The viscous flux and the SA source use these gradients in both schemes, so the first/second-order switch changes the convective flux only.
逐步推导:最小二乘梯度、它的权重与转置
Step by step: the least-squares gradient, its weights and its transpose
第一步,拟合问题。在中心 xi 附近用线性函数 Wi + G·(x − xi) 拟合模板点上的值,取使误差平方和最小的 G(W 的每个分量分别做):
Step 1, the fitting problem. Near the centre xi, fit the values at the stencil points by the linear function Wi + G·(x − xi), and take the G that minimises the sum of squared misfits (for each component of W separately):
第二步,法方程。对 G 求梯度并令其为零:
Step 2, the normal equations. Set the gradient with respect to G to zero:
𝒩i 是 2×2 对称矩阵;只要模板点不全在一条过 xi 的直线上,它就正定。
𝒩i is a symmetric 2×2 matrix, positive definite as long as the stencil points do not all lie on one line through xi.
第三步,显式的权重。2×2 矩阵的逆直接写出(mesh.js 的 weights 正是这几行):
Step 3, explicit weights. The inverse of a 2×2 matrix written out (mesh.js's weights are exactly these lines):
权重 Γij 只依赖几何,与 W 无关:梯度那一遍是线性算子 Γ,Γij 就是它的元素。
The weights Γij depend on the geometry only, not on W: the gradient pass is the linear operator Γ, and the Γij are its entries.
第四步,线性场精确。若 W 是线性场,Wj − Wi = Δxij·∇W 对所有 j 成立,则
Step 4, exact for linear fields. If W is linear, Wj − Wi = Δxij·∇W for every j, and then
每个节点的一组权重都满足它,壁面节点也一样(它们的 u、v、ν̃ 本身就是未知量)。
Every node's weight set satisfies it, the wall nodes' too (their u, v, ν̃ are unknowns themselves).
第五步,前向与转置。Γ 是线性的,前向就是同一组权重作用在 上;伴随把它转置,梯度 Gi 的伴随 按累加送回整个模板:
Step 5, the tangent and the transpose. Γ is linear, so the tangent applies the same weights to ; the adjoint transposes it, and the adjoint of the gradient Gi goes back over the whole stencil as accumulations:
两者是同一个双线性型 按两种次序求和(core.js applyAT 的 “pass 1 reversed”);两个方向画在图 3.3 (b) 里。
Both are the same bilinear form , summed in two orders (core.js applyAT's “pass 1 reversed”); both directions are drawn in Figure 3.3 (b).
第六步,对坐标的前向导数(第 12 节用)。Δxij 随中心移动,;由 ,
Step 6, the forward derivative with respect to the coordinates (used in Section 12). Δxij moves with the centres, ; with ,
核对:本页 24 组权重(邻居个数:8 个控制体有 3 个、8 个控制体有 4 个、8 个控制体有 5 个):第三步的 Γij 与 mesh.js 算出的权重最大相对差 0;ΣjΓijΔxijT 与 I 相差 2.2×10−16;一个线性场的梯度误差 3.3×10−16;沿一个随机坐标方向,第六步的 与几何磁带的前向扫描相差 5.2×10−15;随机向量上 与 相差 3.8×10−16(本页代码在构建时计算)。
Check: this page's 24 weight sets (neighbours: 8 control volumes have 3, 8 control volumes have 4, 8 control volumes have 5): the Γij of Step 3 and mesh.js's weights differ by at most 0; ΣjΓijΔxijT differs from I by 2.2×10−16; a linear field's gradient is off by 3.3×10−16; along a random coordinate direction, Step 6's and a forward sweep of the geometry's tape differ by 5.2×10−15; and on random vectors and differ by 3.8×10−16 (computed by this page's code at build time).
粘性通量:边上的修正平均梯度
The viscous flux: the corrected average gradient on the edge
逐步推导:修正平均梯度与粘性通量的线性化
Step by step: the corrected average gradient and the linearisation of the viscous flux
第一步,拆开平均梯度。对 u、v、T、ν̃ 中的某个分量 φ,记两侧最小二乘梯度的平均为 ∇φavg = ½(GL + GR),Δx = xR − xL,单位向量 Δx̂ = Δx/|Δx|。把平均梯度拆成沿 Δx 与垂直于 Δx 的两部分:
Step 1, split the average gradient. For one component φ of u, v, T, ν̃, let ∇φavg = ½(GL + GR) be the mean of the two least-squares gradients, Δx = xR − xL, and Δx̂ = Δx/|Δx| its unit vector. Split the mean into its parts along and across Δx:
第二步,替换沿 Δx 的部分。沿 Δx 的方向导数改用两个中心值的差 (φR − φL)/|Δx|,得到面上的梯度 ∇fφ(model.js 的 corrected()):
Step 2, replace the part along Δx. The directional derivative along Δx is replaced by the difference of the two centre values, (φR − φL)/|Δx|, which gives the face gradient ∇fφ (model.js corrected()):
第三步,面梯度的导数。∇fφ 对它的四个输入都是线性的:
Step 3, the derivatives of the face gradient. ∇fφ is linear in each of its four inputs:
两侧的梯度只经过“垂直于 Δx 的投影”进入;沿 Δx 只剩两点差,所以不会出现棋盘模式。
The two gradients enter only through the projection across Δx; along Δx only the two-point difference remains, so no checkerboard mode appears.
第四步,通量与系数。面上的粘性通量(第 1 节的 Fv·n)读四个面梯度与两侧平均的系数:
Step 4, the flux and its coefficients. The face's viscous flux (Section 1's Fv·n) reads the four face gradients and coefficients averaged over the two sides:
这里 ∇fu 是以 ∇fu、∇fv 为行的 2×2 矩阵,uavg、μavg、μtavg 是两侧的平均(与第一步的 ∇φavg 同一个写法)。
Here ∇fu is the 2×2 matrix with rows ∇fu and ∇fv, and uavg, μavg, μtavg are the averages of the two sides (written like Step 1's ∇φavg).
第五步,系数的导数。Sutherland 律 μ = μref·1.4T1.5/(T + 0.4) 给 μT = dμ/dT = μ(1.5/T − 1/(T + 0.4));μt = ρν̃fv1(χ),χ = ρν̃/μ,fv1′ = 3cv1³χ²/(χ³ + cv1³)²,于是(其余原始变量固定)
Step 5, the derivatives of the coefficients. Sutherland's law μ = μref·1.4T1.5/(T + 0.4) gives μT = dμ/dT = μ(1.5/T − 1/(T + 0.4)); μt = ρν̃fv1(χ) with χ = ρν̃/μ and fv1′ = 3cv1³χ²/(χ³ + cv1³)², so (the other primitives held)
第六步,链式法则(前向模式)。τn 对 μe 与四个面梯度都是线性的;面梯度 ∇f 对它的四个输入也是线性的,作用在带点的输入上就是它的前向导数(第三步),法向 n 固定。所以
Step 6, the chain rule (forward mode). τn is linear in μe and in the four face gradients; the face gradient ∇f is linear in its four inputs as well, so applied to the dotted inputs it is its own forward derivative (Step 3), with the normal n held. So
能量与 ν̃ 两行同理,按乘积法则逐项加点:
The energy and ν̃ rows follow the same way, a dot on each factor in turn by the product rule:
局部磁带记下的正是这些乘积:面核对 WL、WR 的导数含系数与两点差两部分,对 GL、GR 的导数只含第三步的投影。
These products are exactly what the local tape records: the face kernel's derivative with respect to WL, WR has a coefficient part and a two-point part, and with respect to GL, GR only Step 3's projection.
核对:本页每个内部面上,corrected() 的磁带导数与第三步的公式相差 2.2×10−16;每个控制体上,viscosity() 与 eddy() 的磁带给出的 μT 与第五步三个偏导数与公式相差 9.0×10−16(本页代码在构建时计算)。
Check: on every interior face of this page, the taped derivatives of corrected() and Step 3's formulas differ by 2.2×10−16; in every control volume, μT and the three partials of Step 5 from the tapes of viscosity() and eddy() differ from the formulas by 9.0×10−16 (computed by this page's code at build time).
SA 源项
The SA source
源项是每个控制体一个点的积分:Vi 乘以中心处的 S5。它读三样东西:中心的 W、最小二乘梯度 G(涡量、∇ν̃、∇ρ)、壁面距离 d。
The source is a one-point integral per control volume: Vi times S5 at the centre. It reads three things: the centre's W, the least-squares gradients G (the vorticity, ∇ν̃, ∇ρ), and the wall distance d.
逐步推导:SA 源项对 W、G 与 d 的导数
Step by step: the derivatives of the SA source with respect to W, G and d
源项核的局部 Jacobian Js(15 个输入、1 个输出;第 12 节还要它对壁面距离 d 的导数)由局部磁带求出。这里把磁带做的事按前向模式一层一层写出来:每一层给出它的点。控制体 i 的源项进入残差的 ρν̃ 行:
The source kernel's local Jacobian Js (15 inputs and 1 output; Section 12 also needs its derivative with respect to the wall distance d) comes from the local tape. Here is what the tape does in forward mode, layer by layer: each layer gives its dot. The source of control volume i enters the residual's ρν̃ row:
Q 是第 1 节 S5 方括号里的净源项,s = −S5。输入是中心值 Wi = (ρ, u, v, T, ν̃)、梯度 Gi(10 个分量)与 di。
Q is the net source inside the bracket of Section 1's S5, and s = −S5. The inputs are the centre values Wi = (ρ, u, v, T, ν̃), the gradients Gi (10 entries) and di.
第一步,分子粘性。ν = μ/ρ,μ(T) 是 Sutherland 律:
Step 1, the molecular viscosity. ν = μ/ρ, and μ(T) is Sutherland's law:
第二步,χ = ν̃/ν = ρν̃/μ:
Step 2, χ = ν̃/ν = ρν̃/μ:
第三步,三个阻尼函数只依赖 χ(fv2′ 用商的求导法则,1 + χfv1 − χ(fv1 + χfv1′) = 1 − χ²fv1′):
Step 3, the three damping functions depend on χ only (fv2′ by the quotient rule, with 1 + χfv1 − χ(fv1 + χfv1′) = 1 − χ²fv1′):
第四步,B = ν̃fv2/(κ²d²)。ν̃ 既直接出现,又经 χ 出现,而 ν̃·∂χ/∂ν̃ = χ;ρ 与 T 只经 χ 进入:
Step 4, B = ν̃fv2/(κ²d²). ν̃ appears directly and through χ, with ν̃·∂χ/∂ν̃ = χ; ρ and T enter through χ only:
第五步,涡量。ω = ∂v/∂x − ∂u/∂y 取自最小二乘梯度 Gi,Ω = |ω|:
Step 5, the vorticity. ω = ∂v/∂x − ∂u/∂y comes from the least-squares gradients Gi, and Ω = |ω|:
第六步,S̃ 的两支。第一支 S̃ = Ω + B:FB = ∂S̃/∂B = 1,FΩ = ∂S̃/∂Ω = 1。第二支 S̃ = Ω + Ω(c2²Ω + c3B)/Ξ,Ξ = (c3 − 2c2)Ω − B,用商的求导法则:
Step 6, the two branches of S̃. First branch, S̃ = Ω + B: FB = ∂S̃/∂B = 1 and FΩ = ∂S̃/∂Ω = 1. Second branch, S̃ = Ω + Ω(c2²Ω + c3B)/Ξ with Ξ = (c3 − 2c2)Ω − B, by the quotient rule:
在接缝 B = −c2Ω 处 Ξ = (c3 − c2)Ω,第二支的分式等于 −c2Ω:两支的值都是 (1 − c2)Ω,FB 与 FΩ 也都等于 1,所以 S̃ 在接缝处一阶连续。于是 。本页求源项的 11 个控制体里,第二支在 0 个上起作用。
At the seam B = −c2Ω, Ξ = (c3 − c2)Ω and the second branch's fraction equals −c2Ω: both branches give (1 − c2)Ω, and FB and FΩ both equal 1, so S̃ is continuously differentiable across the seam. Hence . Of this page's 11 control volumes, the second branch is active in 0.
第七步,r 与截断。r0 = ν̃/(κ²d²S̃);未截断时
Step 7, r and its cap. r0 = ν̃/(κ²d²S̃); uncapped,
截断时 r = 10 是常数,:那里 fw 对任何输入都没有导数。本页 1 个控制体被截断。
When capped, r = 10 is a constant and : there fw has no derivative with respect to any input. On this page 1 control volumes are capped.
第八步,g 与 fw。对 fw = g(1 + cw3⁶)1/6(g⁶ + cw3⁶)−1/6 求导,(g⁶ + cw3⁶)−1/6 − g⁶(g⁶ + cw3⁶)−7/6 = cw3⁶(g⁶ + cw3⁶)−7/6:
Step 8, g and fw. Differentiating fw = g(1 + cw3⁶)1/6(g⁶ + cw3⁶)−1/6, with (g⁶ + cw3⁶)−1/6 − g⁶(g⁶ + cw3⁶)−7/6 = cw3⁶(g⁶ + cw3⁶)−7/6:
第九步,净源项。把以上各层代进 Q():
Step 9, the net source. Put the layers above into Q ():
第十步,守恒形式的两项。密度梯度项 a∇ρ·∇ν̃ 与 cb2 项 ρb|∇ν̃|² 的导数直接写出:
Step 10, the two terms of the conservative form. The derivatives of the density-gradient term a∇ρ·∇ν̃ and the cb2 term ρb|∇ν̃|² written directly:
第十一步,装配 Js。s 对每个输入的导数是以上各项之和,其中 −ρQ 对 ρ 的导数是 −Q − ρ∂Q/∂ρ;乘以 Vi 就是 Js 的一行。16 个输入里有 10 个出现:ρ、T、ν̃、∇ρ 的两个分量、∂u/∂y、∂v/∂x、∇ν̃ 的两个分量与 d;u、v、∂u/∂x、∂v/∂y 与 ∇T 的导数恒为零。各部分在本页的大小见图 3.6。
Step 11, assemble Js. The derivative of s with respect to each input is the sum of the terms above, where −ρQ contributes −Q − ρ∂Q/∂ρ to the ρ entry; times Vi it is the row Js. 10 of the 16 inputs appear: ρ, T, ν̃, the two components of ∇ρ, ∂u/∂y, ∂v/∂x, the two components of ∇ν̃, and d; the derivatives with respect to u, v, ∂u/∂x, ∂v/∂y and ∇T are identically zero. Figure 3.6 shows how large each part is on this page.
核对:把上面十一步照写成代码(enrich_data.js 的 saHand,不调用 model.js 的源项),在 U* 的每个求源项的控制体(11 个)上与 model.js source() 的磁带比较:16 个导数的最大相对差 1.9×10−15,源项值 3.8×10−15。其中第二支 0 个、r 截断 1 个、生成项为负(ft2 > 1)4 个(本页代码在构建时计算)。
Check: the eleven steps written out as code (enrich_data.js saHand, which does not call model.js's source) and the tape of model.js source() compared in every control volume where the source is evaluated (11 of them) at U*: the 16 derivatives differ by at most 1.9×10−15 (relative), the source's value by 3.8×10−15. Among them 0 are on the second branch, 1 capped, and 4 have negative production (ft2 > 1) (computed by this page's code at build time).
第三、六、七、八步的公式与接缝处的一阶连续另由 sympy 符号验证(check_enrich_sympy.py)。
The formulas of Steps 3, 6, 7 and 8 and the continuity at the seam are also verified symbolically by sympy (check_enrich_sympy.py).
到这里,内部面已经完整:两侧都有控制体,面循环读两侧的状态与梯度。边界上的面只有一侧;物面、来流与出口的条件怎样写进通量、又替换哪些行,是第 4 节的内容。
Interior faces are now complete: they have a control volume on each side, and the face loop reads the states and gradients of both. A boundary face has one side only; how the conditions of the wall, the inflow and the outlet enter its flux, and which rows they replace, is the subject of Section 4.
边界条件
Boundary conditions
内圈:强条件的无滑移绝热壁
Inner ring: the no-slip adiabatic wall, strongly
壁面节点的 ρu、ρv、ρν̃ 三行在所有循环之后被替换成 U 本身,于是解满足 u = v = ν̃ = 0。连续方程与能量方程不能替换,它们仍是通量平衡。壁面半面对它们没有贡献:质量通量 ρu·n = 0,能量通量为零(绝热,且应力不做功),所以面循环跳过壁面半面。
The ρu, ρv and ρν̃ rows of a wall node are replaced by U itself after all the loops, so the solution satisfies u = v = ν̃ = 0. The continuity and energy equations cannot be replaced; they remain flux balances. The wall half-faces add nothing to them: the mass flux ρu·n = 0 and the energy flux is zero (adiabatic, and the stress does no work), so the face loop skips the wall half-faces.
外圈:远场
Outer ring: the far field
来流节点的 ρu、ρv、ρν̃ 三行在循环之后替换成 Uk − UρW∞,k:以节点自己的 ρ 给定 u = u∞、ν̃ = ν̃∞。质量行保留,ρ 只经来流半面上给定的质量通量 ρ∞u∞·n 进入。能量行在替换之前先减去 u∞ 乘两行动量行:这时动量行的值正是经来流半面作用在节点上的粘性牵引力(反作用),能量行由此得到同一个牵引力做的功。来流半面上的通量是边界状态 (ρ∞, u∞, v∞, Ti, ν̃∞) 的对流通量,不含粘性通量,也没有热流。出口半面:本节点的状态,压力换成 p∞ = 1,没有粘性通量。一个节点只要有一个来流半面就是来流节点,所以两个交界节点也是来流节点,它们的出口半面只进入质量行与能量行。附录 B 说明为什么这样是伴随一致的。
The ρu, ρv and ρν̃ rows of an inflow node are replaced by Uk − UρW∞,k after the loops: u = u∞ and ν̃ = ν̃∞ at the node's own ρ. The mass row stays, and ρ enters only through the given mass flux ρ∞u∞·n on the inflow half-faces. Before the replacement the energy row subtracts u∞ times the two momentum rows: at that point the momentum rows hold exactly the viscous traction on the node through its inflow half-faces (the reaction), so the energy row takes the work of that same traction. The flux through an inflow half-face is the convective flux of the boundary state (ρ∞, u∞, v∞, Ti, ν̃∞), with nothing viscous and no heat flux. An outlet half-face: the node's own state with its pressure replaced by p∞ = 1, and nothing viscous. A node with one inflow half-face is an inflow node, so the two junction nodes are inflow nodes too, and their outlet half-faces enter their mass and energy rows only. Appendix B explains why this is adjoint-consistent.
在解处冻结的分支
The branches, frozen at the solution
离散残差里有几处不可导点。导数(前向、伴随、复数步长)都在当前解所在的那一侧分支上取;只要解离分支点足够远,差分的步长就跨不过去。下表列出二阶格式在收敛解处的距离:
The discrete residual has a few points where it is not differentiable. Every derivative (tangent, adjoint, complex step) is taken on the branch the solution sits on; as long as the solution is far enough from a switch, a finite-difference step cannot cross it. The table lists the distances at the converged second-order solution:
| 分支 | branch | 当前解处的余量 | margin at the solution |
|---|---|---|---|
| Ω = |ω| 在 ω = 0 | Ω = |ω| at ω = 0 | min|ω| / max|ω| = 0.008 | min|ω| / max|ω| = 0.008 |
| Roe 的 |q̃| 在 q̃ = 0 | Roe's |q̃| at q̃ = 0 | min|q̃| = 7.6×10−3(一阶时壁面节点之间的面上正好为 0,见下) | min|q̃| = 7.6×10−3 (exactly 0 on the faces between wall nodes at first order, see below) |
| S̃ 的两个分支 B = −c₂Ω | the two branches of S̃, B = −c₂Ω | min |B + c₂Ω| / Ω = 0.798(该处一阶导数连续) | min |B + c₂Ω| / Ω = 0.798 (the first derivative is continuous there) |
| r 的截断 r = 10 | the cap r = 10 | min |r₀ − 10| / 10 = 0.787(fw 在 r = 10 已饱和,导数 ~10⁻³¹) | min |r₀ − 10| / 10 = 0.787 (fw is saturated at r = 10; its slope is ~10⁻³¹) |
| 壁面距离的最近边切换 | the wall distance switching edges | 凸物体:到凸多边形的距离一阶连续可微 | a convex body: the distance to a convex polygon is continuously differentiable |
r 在 1 个控制体上被截断。修正分支只出现在 3 个来流节点上,而这些节点的 ν̃ 行被替换、源项不计算,所以本页二阶格式的残差用不到它(上表的余量也只在计算源项的控制体上取)。格点页一阶格式有一处例外:两个壁面节点之间的面,两侧速度都正好是 0,所以 q̃ = 0,正好落在 |q̃| 的不可导点上。导数取 |q̃| 的正分支;这些导数项只与壁面节点的速度相乘,而任何前向解 v 在壁面节点的速度分量上恒为零(它们的行被替换),所以设计导数与分支的选法无关,只有壁面节点动量分量的伴随值依赖它。
r is capped in 1 control volume. The modified branch occurs only at 3 inflow nodes, whose ν̃ rows are replaced and whose source is not evaluated, so this page's second-order residual does not use it (the margins of the table are taken over the control volumes whose source is evaluated). The node page at first order has one exception: on a face between two wall nodes both velocities are exactly 0, so q̃ = 0 and the face sits exactly on the kink of |q̃|. The derivative takes the positive branch of |q̃|; these terms multiply only the wall nodes' velocities, and every tangent solution v is zero in the wall nodes' velocity components (their rows are replaced), so the design derivatives do not depend on the choice; only the adjoint of the wall nodes' momentum components does.
下面的演示把这些分支画出来:fv1(χ)、fw(r) 与它在 r = 10 的截断、S̃/Ω 随 B/Ω 的两支,并把当前解(页首所选的阶)每个计算源项的控制体的值标在曲线上(ν̃ 行被替换的壁面节点与来流节点不画)。点离开分支点有多远,就是上表的余量。
The demo below draws these branches: fv1(χ), fw(r) with its cap at r = 10, and the two branches of S̃/Ω against B/Ω, with every control volume of the current solution (at the order chosen in the header) whose source is evaluated marked on the curves (the wall and inflow nodes, whose ν̃ rows are replaced, are left out). How far the points sit from a switch is the margin of the table above.
残差 = 几遍循环:原始变量、梯度、面、源项、强边界行
The residual = passes: primitives, gradients, faces, source, strong rows
标量页面的残差是一个面循环。这里一个面要读两侧的梯度,而梯度要读整个模板的值,所以残差分成几遍:先把所有控制体的原始变量算出来,再算所有梯度,然后才是面通量和源项。
On the scalar pages the residual is one face loop. Here a face reads the gradients on both sides, and a gradient reads the values over its whole stencil, so the residual comes in passes: first the primitive variables of every control volume, then every gradient, and only then the face fluxes and the source.
π 在每个控制体上独立地把守恒变量换成原始变量;Γ 是线性的最小二乘算子(权重只依赖几何);F 是面通量的装配,S 是源项;格点页最后还有第 4 遍,替换壁面节点与来流节点的强边界行。下面的演示逐句执行这几遍:543 步,可以用上方的按钮直接跳到某一遍。
π turns each control volume's conserved variables into primitives, independently; Γ is the linear least-squares operator (its weights depend on the geometry only); F assembles the face fluxes and S the source. The demo below executes the passes statement by statement: 543 steps, and the buttons above it jump straight to a pass.
最后一步 max|R| 在舍入误差量级:U* 是收敛解。注意第 4 遍:壁面节点的三行在所有循环之后才被替换,面循环写进这些行的值全部被覆盖;来流节点的能量行先减去 u∞ 乘两行动量行,然后它的三行被替换。第 9 节的伴随要先处理这件事。
At the last step max|R| is at round-off: U* is the converged solution. Note pass 4: the three rows of each wall node are replaced after all the loops, overwriting whatever the face loop wrote there; each inflow node's energy row first subtracts u∞ times its two momentum rows, and then its three rows are replaced. The adjoint of Section 9 has to deal with this first.
求解:Jacobian、近似 Jacobian 与 Gauss–Seidel
The solve: the Jacobian, the approximate Jacobian and Gauss–Seidel
从残差到 Jacobian
From the residual to the Jacobian
A = ∂R/∂U 是 120×120 的矩阵,由 5×5 的块组成。一个面的通量读两侧的值与梯度,梯度又读整个模板,所以 A 的一行不只连到邻居,还连到邻居的邻居:264 个非零块。
A = ∂R/∂U is a 120×120 matrix of 5×5 blocks. A face's flux reads the values and gradients on both sides, and a gradient reads its whole stencil, so a row of A reaches past the neighbours to the neighbours' neighbours: 264 non-zero blocks.
近似 Jacobian:一阶 Roe 加薄剪切层
The approximate Jacobian: first-order Roe plus the thin shear layer
Gauss–Seidel 用的不是 A,而是一个只连接面两侧的近似 P:对流部分是一阶 Roe(Jc(U) = ∂(Fc(U)·n̂)/∂U 是物理通量的 Jacobian,|J̃c| = Σk|Λk|rklkT 是它在两侧中心状态的 Roe 平均处取绝对值,lk 是左特征向量),粘性部分是薄剪切层(只保留修正梯度沿 Δx 的两点差分,系数冻结):
Gauss–Seidel does not use A but an approximation P that couples only the two sides of each face: first-order Roe for the convective part (Jc(U) = ∂(Fc(U)·n̂)/∂U is the Jacobian of the physical flux, and |J̃c| = Σk|Λk|rklkT its absolute value at the Roe average of the two centre states, lk being the left eigenvectors), and the thin shear layer for the viscous part (only the two-point difference along Δx of the corrected gradient, with frozen coefficients):
Θf 是薄剪切层矩阵乘上两点系数 θf = nf·Δx/|Δx|²:动量行 θfμe(I + ⅓n̂n̂T),能量行加上功与导热 θfke,ν̃ 行 θfρa。(ρν̃, ρν̃) 对角元再加上 SA 源项对 ρν̃ 的导数,只在它为正(耗散占优、使对角增强)时加;对角块还加上伪时间项 V/Δt。壁面节点的三行是单位行;来流节点的三行是 ek − W∞,keρ,能量行是与残差相同的组合 E − u∞·M。P 有 120 个非零块。
Θf is the thin-shear-layer matrix times the two-point coefficient θf = nf·Δx/|Δx|²: the momentum rows θfμe(I + ⅓n̂n̂T), the energy row adds the work and the conduction θfke, and the ν̃ row θfρa. The (ρν̃, ρν̃) entry also receives the SA source's derivative with respect to ρν̃ where it is positive (destruction dominating, so it strengthens the diagonal), and the diagonal blocks the pseudo-time term V/Δt. The three rows of a wall node are unit rows; the three rows of an inflow node are ek − W∞,keρ, and its energy row is the residual's own combination E − u∞·M. P has 120 non-zero blocks.
逐步推导:薄剪切层矩阵从哪里来
Step by step: where the thin-shear-layer matrix comes from
第一步,只留两点部分。在第 3 节的面梯度里只保留沿 Δx 的两点差,∇fφ ≈ (φR − φL)Δx/|Δx|²,并冻结所有系数。于是速度的面梯度矩阵是 ∇fu ≈ Δu ΔxT/|Δx|²(Δu = uR − uL)。
Step 1, keep only the two-point part. In the face gradient of Section 3 keep only the two-point difference along Δx, ∇fφ ≈ (φR − φL)Δx/|Δx|², and freeze every coefficient. The velocity's face-gradient matrix is then ∇fu ≈ Δu ΔxT/|Δx|² (Δu = uR − uL).
第二步,代入应力:
Step 2, put it into the stress:
第三步,Δx 平行于 n 时。Δx = |Δx|n̂、n = |n|n̂,两点系数 θf = n·Δx/|Δx|² = |n|/|Δx|,第二步化为
Step 3, when Δx is parallel to n. With Δx = |Δx|n̂ and n = |n|n̂, the two-point coefficient is θf = n·Δx/|Δx|² = |n|/|Δx|, and Step 2 becomes
第四步,能量与 ν̃ 两行。功 uavg·τn 用第三步的 τn,导热与 ν̃ 的扩散也只剩两点差(unavg = uavg·n̂):
Step 4, the energy and ν̃ rows. The work uavg·τn uses Step 3's τn, and the conduction and the ν̃ diffusion keep their two-point differences only (unavg = uavg·n̂):
第五步,Θf。把三式按原始变量 (ρ, u, v, T, ν̃) 排成矩阵,就是上文近似 Jacobian 里的 Θf:Fv ≈ Θf(WR − WL),∂Fv/∂UR ≈ ΘfΠR,∂Fv/∂UL ≈ −ΘfΠL(Π = ∂W/∂U,第 8 节)。Δx 不平行于 n 时(歪斜的面),第二步里 Δx(Δu·n) 与 (Δu·Δx)n 两项不再化成 n̂n̂T:Θf 只是近似。P 本来只需要近似:它只影响迭代的快慢。
Step 5, Θf. Arranging the three in the primitive columns (ρ, u, v, T, ν̃) gives the Θf of the approximate Jacobian above: Fv ≈ Θf(WR − WL), ∂Fv/∂UR ≈ ΘfΠR, ∂Fv/∂UL ≈ −ΘfΠL (Π = ∂W/∂U, Section 8). When Δx is not parallel to n (a skewed face), the terms Δx(Δu·n) and (Δu·Δx)n of Step 2 no longer reduce to n̂n̂T: Θf is an approximation. P only needs to be one: it affects how fast the iteration converges, nothing else.
核对:把本页每个内部面的 Δx 转到 n 的方向、两侧取同一状态、梯度取零,粘性核的磁带给出的 ∂Fv/∂WR 与第三、四步的 Θf 相差 7.5×10−16(相对 Frobenius 范数)。本页的面并不正交:48 个内部面上 Δx 与 n 的夹角平均 18.8°,最大 42.4°(本页代码在构建时计算)。
Check: with the line Δx of every interior face of this page turned along n, the same state on both sides and zero gradients, the viscous kernel's taped ∂Fv/∂WR and the Θf of Steps 3 and 4 differ by 7.5×10−16 (relative, Frobenius norm). This page's faces are not orthogonal: over the 48 interior faces the angle between Δx and n is 18.8° on average and 42.4° at most (computed by this page's code at build time).
P 与 A 差多少?图 6.2 在一个面上比较磁带给出的直接块(一阶面状态、梯度固定,第 3 节 Roe 与粘性线性化的全部项)与 P 的块(第 3 节 Roe 第五步的前两项加上面的 Θf)。
How far is P from A? Figure 6.2 compares, on one face, the taped direct block (first-order face states, gradients held, every term of Section 3's linearisations of the Roe and viscous fluxes) with P's block (the first two terms of Step 5 of Section 3's Roe derivation plus the Θf above).
R(U) = 0 怎样解
How R(U) = 0 is solved
用第 3 节的半离散方程 V dU/dt = −R(U) 做伪时间推进。记 ΔU = Uk+1 − Uk,每一步用隐式(后向 Euler)格式,并把 R 在当前状态线性化:
March the semi-discrete equation of Section 3, V dU/dt = −R(U), in pseudo time. With ΔU = Uk+1 − Uk, each step is implicit (backward Euler), with R linearised about the current state:
把 AΔU 移到左边,就是每一步要解的线性方程:
Moving AΔU to the left gives the linear system of each step:
V/Δt 是对角的:每个控制体取自己的伪时间步 Δti,由局部 CFL 数和该控制体的对流、粘性谱半径决定,所以各处推进的“时间”并不相同。把 A 换成近似 Jacobian Â,左边就是上面的 P;再用两次对称块 GS 近似求解(记作 K),就是本页的迭代:
V/Δt is diagonal: each control volume takes its own pseudo-time step Δti, set by a local CFL number and the control volume's convective and viscous spectral radii, so different places advance by different amounts of “time”. Replacing A by the approximate Jacobian  turns the left-hand side into the P above; solving with it approximately, by two symmetric block GS sweeps (written K), gives this page's iteration:
一次对称扫描是 i = 1…N 的前扫接 N…1 的回扫;每个控制体解一个 5×5 的块方程,用到的是邻居最新的值。CFL 从 5 起按残差下降放大,上限 200;每 50 步检查一次,若这 50 步里最小的残差没有比此前最好的值再低 10%,就把上限减半(不低于 10),大步长下偶尔出现的伪时间二周期由此消失。一个 5×5 块的求逆就是全部的“线性代数”,不形成、不分解大矩阵。
One symmetric sweep is a forward pass over i = 1…N followed by a backward pass over N…1; each control volume solves a 5×5 block equation with its neighbours' latest values. The CFL number starts at 5 and grows as the residual falls, capped at 200; every 50 steps, if the smallest residual of those 50 is not 10 % below the best before, the cap is halved (down to 10), which settles the pseudo-time two-cycle that a large step occasionally produces. Inverting a 5×5 block is all the “linear algebra” there is: no large matrix is formed or factorised.
伪时间步只进 P(从而进 K),不进 R:它决定迭代怎样走、走多快,不改变终点。收敛时 R(U*) = 0,与 Δt、Â 和扫描次数都无关;本节开头的 A = ∂R/∂U 也不含时间项,所以第 8、9 节的前向与伴随方程 A v = −f、ATψ = −g 里也没有时间项。第 10、11 节迭代求解它们时用的也是这个 P,它同样只影响收敛的快慢。推进中还有一道保正:若整步会让某个控制体的 ρ 或 T 变化超过 20%,或让 ν̃ 变负,就按比例缩短这个控制体的步长;它也只改变路径。
The pseudo-time step enters P (and so K), not R: it decides how the iteration travels and how fast, not where it ends. At convergence R(U*) = 0 whatever Δt, Â and the number of sweeps; the A = ∂R/∂U at the start of this section carries no time term either, so neither do the tangent and adjoint equations of Sections 8 and 9, A v = −f and ATψ = −g. The iterations that solve them in Sections 10 and 11 use this P as well, and there too it only sets how fast they converge. The marching also keeps the state positive: if a full step would change a control volume's ρ or T by more than 20%, or make its ν̃ negative, that control volume's step is shortened in proportion; this too changes only the path.
算例的状态
The state of the test case
二阶格式在第 199 次迭代满足判据(每个方程按自身尺度的残差都小于 10−13),然后继续到舍入底 9.1×10−16;一阶格式在第 45 次(这些是构建页面时在 Node.js 里测得的;页首的状态行是你的浏览器重算的,舍入底的末位可能不同)。收敛解处 ρ 在 [0.421, 1.250],p 在 [0.719, 2.254],ν̃ 最小 0.00818(来流 0.0600):处处为正,标准 SA 不需要任何截断。格点页第 0 级网格上的状态离连续解很远:24 个节点里 8 个壁面节点与 5 个来流节点的速度被强条件固定,流体只能从其余 11 个节点之间通过,最快处达到来流速度的 3.1 倍;出口的牵引力把压力维持在 p∞ 附近,密度低的地方温度就高(T 最高 1.83)。第 7 节的加密表与附录 A 说明这是离散误差:两种格式的阻力与导数随网格加密相互靠近。
The second-order scheme meets the criterion (every equation's residual, scaled by its own size, below 10−13) at iteration 199 and runs on to the round-off floor 9.1×10−16; the first-order scheme at iteration 45 (measured in Node.js when the page was built; the status line in the header is recomputed in your browser, and the last digits of the floor can differ). At the converged state ρ lies in [0.421, 1.250], p in [0.719, 2.254], and ν̃ is at least 0.00818 (free stream 0.0600): positive everywhere, and the standard SA needs no clipping. On level 0 the node page's state is far from the continuous solution: of the 24 nodes, the 8 wall nodes and the 5 inflow nodes have their velocity fixed by strong conditions, the flow has to pass between the other 11, and at its fastest it reaches 3.1 times the free-stream speed; the outlet's traction holds the pressure near p∞, so where the density is low the temperature is high (up to T = 1.83). The refinement table of Section 7 and Appendix A show that this is discretisation error: the drag and the derivatives of the two schemes approach each other as the mesh is refined.
图 6.4 把第 1 节的 SA 变量画在收敛解 U* 上,并标出第 4 节表中两个分支在哪些控制体上起作用。
Figure 6.4 draws the SA variables of Section 1 on the converged U*, and marks where the two branches of Section 4's table are active.
目标函数:阻力系数
The objective: the drag coefficient
F 是流体作用在物体上的力。格点页上壁面节点的动量行被替换了,力要从被替换之前的动量残差里取出来:一个壁面节点经内部对偶面流出的动量,等于物体经壁面半面作用在它上面的力;流体对物体的力是这个力的反作用。所以 F = −Σ壁面节点 Ri动量(替换前)。这是与离散动量守恒完全一致的“反作用力”。
F is the force the fluid exerts on the body. On the node page the wall nodes' momentum rows are replaced, so the force has to come from the momentum residual before the replacement: the momentum a wall node sends out through its interior dual faces equals the force the body exerts on it through its wall half-faces, and the fluid's force on the body is the reaction to that force. So F = −Σwall nodes Rimomentum (before replacement). This is the consistent “reaction force”: it agrees exactly with the discrete momentum balance.
粗网格的阻力有多准
How accurate the coarse-mesh drag is
同一个问题在第 1、2 级加密网格(每级把每个单元一分为四)上的阻力:
The drag of the same problem on the meshes of levels 1 and 2 (each level divides every cell into four):
| 级 | level | 控制体 | control volumes | CD | 单边公式 | one-sided formula |
|---|---|---|---|---|---|---|
| 0 | 24 | 50.9985 | 45.3872 | |||
| 1 | 80 | 11.3766 | 13.2715 | |||
| 2 | 288 | 7.2709 | 8.1598 |
第 0 级的阻力是第 2 级的 7.0 倍:这张网格上 13 个节点的速度被强条件固定(第 6 节)。随着加密两种格式相互靠近(第 2 级:格点 7.271,格心 6.410;附录 A 算到第 4 级:格点 6.456,格心 6.414);单边公式(节点压力加节点梯度应力)比反作用力收敛得慢。从第 0 级到第 4 级,本页的 CD 变化 −87%,三个导数:dCD/dα −93%、dCD/dM −75%、dCD/dμref −36%;其中对 α 的导数比阻力变得多(第 12 节、附录 A)。本页关心的是离散问题的导数:它在每一级网格上都是那一级离散问题的精确导数,但第 0 级的值不能当作连续问题导数的近似。
The level-0 drag is 7.0 times level 2's: on this mesh 13 nodes have their velocity fixed by strong conditions (Section 6). With refinement the two schemes approach each other (level 2: node 7.271, cell 6.410; Appendix A goes to level 4: node 6.456, cell 6.414); the one-sided formula (nodal pressure plus the nodal gradients' stress) converges more slowly than the reaction force. From level 0 to level 4 this page's CD changes by −87%, and its three derivatives: dCD/dα by −93%, dCD/dM by −75%, dCD/dμref by −36%; the derivatives with respect to α change more than the drag (Section 12 and Appendix A). What this page is about is the derivative of the discrete problem: on every mesh it is the exact derivative of that mesh's discrete problem, but the level-0 value must not be taken as an approximation of the continuous problem's derivative.
伴随方程的右端项
The right-hand side of the adjoint equation
g = ∂CD/∂U 是伴随方程 ATψ = −g 的右端。它等于 residual_b 去掉第 4 遍(强边界行)那一步(第 9 节):权重 −eD/q∞ 放在壁面节点的动量行上,直接进入面循环的反向。这些行在替换之前的值正是目标所用的;若保留那一步,权重会经被替换的单位行直接进 ,结果就错了(两者相差 2.0,而去掉那一步与磁带给出的 g 相差 7.8×10−16,都按 g 的最大分量归一)。本页把整个目标函数录成一条磁带,反向扫描一次得到它:种子 ,扫描返回的 就是 g。
g = ∂CD/∂U is the right-hand side of the adjoint equation ATψ = −g. It equals residual_b without its pass 4, the strong rows (Section 9): the weights −eD/q∞ on the wall nodes' momentum rows go straight into the reversed face loop. Those rows' values before the replacement are exactly what the objective uses; keeping the step would send the weights through the replaced unit rows straight into , which is wrong (it differs by 2.0, while the version without the step differs from the taped g by 7.8×10−16, both relative to the largest entry of g). This page gets it from one reverse sweep of a tape of the objective: with the seed the sweep returns .
逐步推导:CD 的偏导数
Step by step: the partial derivatives of CD
第 8 节的 dCD/dD = ∂CD/∂D + ψTf 里,∂CD/∂D 是固定 U 时的偏导数。对三个流动参数它们都有闭式。
In Section 8's dCD/dD = ∂CD/∂D + ψTf, ∂CD/∂D is the partial derivative at fixed U. For the three flow parameters it has a closed form.
第一步,F 与参数。CD = F·eD/q∞。格点页的 F 是壁面节点替换前的动量行之和取负,这些行只收集内部对偶面的通量(壁面半面在面循环里跳过)。α 与 M 只进入来流数据,而壁面节点的对偶面不碰来流,所以固定 U 时 F 与 α、M 无关;μref 进入粘性通量。
Step 1, F and the parameters. CD = F·eD/q∞. On the node page F is minus the sum of the wall nodes' momentum rows before replacement, and those rows collect the fluxes of interior dual faces only (the face loop skips the wall half-faces). α and M enter the inflow data only, and no wall node's dual face touches the inflow, so at fixed U, F does not depend on α or M; μref enters the viscous fluxes.
第二步,α。deD/dα = (−sin α, cos α) = eL,与来流垂直,所以固定流场时转动来流方向,阻力的变化就是升力系数:
Step 2, α. deD/dα = (−sin α, cos α) = eL, perpendicular to the free stream, so turning the free-stream direction with the flow held changes the drag by the lift coefficient:
第三步,M。q∞ = 0.7M²,dq∞/dM = 2q∞/M:
Step 3, M. q∞ = 0.7M², dq∞/dM = 2q∞/M:
第四步,μref。F 里依赖 μref 的只有粘性应力 τn,它对 μe 是线性的。μ = μref·1.4T1.5/(T + 0.4) 与 μref 成正比;μt = ρν̃fv1(χ) 经 χ = ρν̃/μ 依赖它:
Step 4, μref. The only part of F that depends on μref is the viscous stress τn, which is linear in μe. μ = μref·1.4T1.5/(T + 0.4) is proportional to μref; μt = ρν̃fv1(χ) depends on it through χ = ρν̃/μ:
格点页把它加在每个碰到壁面节点的内部对偶面上,符号与该节点在面上是 L 还是 R 一致(两个壁面节点之间的面两边抵消):
The node page sums it over the interior dual faces that touch a wall node, signed by whether the node is the face's L or R (a face between two wall nodes cancels):
(±) 在壁面节点是面的 L 时取 +、是 R 时取 −。没有涡粘性时,这就是 CD 的粘性部分除以 μref:固定流场时粘性应力与 μref 成正比。涡粘性使它变小:固定 ν̃ 时 μref 增大,χ 减小,μt 也减小。
(±) is + where the wall node is the face's L and − where it is its R. Without eddy viscosity this is the viscous part of CD divided by μref: with the flow held, the viscous stress is proportional to μref. The eddy viscosity lowers it: at fixed ν̃ a larger μref means a smaller χ and a smaller μt.
第五步,g = ∂CD/∂U。F 读哪些状态,g 就在哪些控制体上非零:壁面节点的动量行读两侧的 W 与 G,G 又读整个模板。图 7.2 画出 g。
Step 5, g = ∂CD/∂U. g is non-zero exactly in the control volumes whose state F reads: the wall nodes' momentum rows read W and G on both sides, and G reads its whole stencil. Figure 7.2 draws g.
核对:本页 CL = −8.006551,与整条磁带给出的 ∂CD/∂α|U = −8.006551 相对差 0;
Check: on this page CL = −8.006551, and the whole-residual tape gives ∂CD/∂α|U = −8.006551, a relative difference of 0; −2CD/M = −509.9848 against the tape's −509.9848, 1.1×10−16; Step 4's sum is 187.1631 against the tape's 187.1631, 0. g is non-zero in 24 control volumes (computed by this page's code at build time).
matrix-free 前向:计算
Matrix-free forward mode: computing
为什么需要 A 与 AT 的乘积
Why products with A and AT are needed
对任何设计变量 D(迎角、马赫数、参考粘度、每个节点坐标),
For any design variable D (the angle of attack, the Mach number, the reference viscosity, each node coordinate),
前向每个设计变量解一次,伴随解一次就得到所有设计变量的导数。两种迭代都只需要一个动作:(residual_d)或 (residual_b)。
The tangent needs one solve per design variable, the adjoint one solve for all of them. Both iterations need only one action: (residual_d) or (residual_b).
记号:点与横线
Notation: the dot and the bar
从这里起,对离散代码的求导都用自动微分的记号(Griewank 与 Walther): 是程序变量 x 的前向(切线)导数, 是它的反向(伴随)导数;反向把语句倒过来执行,累加写作 ,前向里被覆盖的量清零,。两个求解的结果沿用本页的名字 v 与 ψ:
From here on, every derivative of the discrete code is written in the notation of algorithmic differentiation (Griewank and Walther): is the forward (tangent) derivative of a program variable x, its reverse (adjoint) derivative; reverse mode runs the statements backwards, accumulating, , and zeroing what the forward code overwrote, . The two solves keep this page's names, v and ψ:
的显式部分 ∂CD/∂D 来自目标的反向扫描(种子 ;第 7 节的 g 就是这种扫描对 U 给出的 )。最后一行是对偶恒等式:第 9 节的点积检验在随机向量上核对它,第 11 节前向与伴随的导数估计逐步相等是它在迭代上的形式。
The explicit part ∂CD/∂D of comes from a reverse sweep of the objective with (Section 7's g is the of such a sweep). The last line is the duality identity: the dot-product test of Section 9 checks it on random vectors, and the equal derivative estimates of the tangent and the adjoint iterations in Section 11 are its form along the iterations.
点、横线与 δ 各有其位。点与横线是离散代码的前向与反向导数(第 8–14、16 节与各节的逐步推导);代码与演示用 Tapenade 的名字,x_d ≡ 、x_b ≡ :residual_d 返回 R_d = A·U_d,residual_b 返回 U_b = AT·R_b。δ 是连续函数的变分,只出现在附录 A 的连续伴随里。
The dot, the bar and δ each have their place. The dot and the bar are the forward- and reverse-mode derivatives of the discrete code (Sections 8–14 and 16, and the step-by-step derivations); the code and the demos use Tapenade's names, x_d ≡ and x_b ≡ : residual_d returns R_d = A·U_d, residual_b returns U_b = AT·R_b. δ is the variation of a continuous function and appears only in the continuous adjoint of Appendix A.
对局部核求导:局部磁带
Differentiating the local kernels: local tapes
残差由三种核拼成:原始变量 π(每个控制体 5 进 5 出)、面核(内部对偶面读两侧的 W 与 G,共 30 个输入、5 个输出)、源项核(15 进 1 出)。每个核只写一次,同一份代码可以用实数、复数或“局部磁带”运行。磁带记下核里每个运算的值与它对一两个操作数的偏导数;向前扫一遍得到方向导数,向后扫一遍得到转置。本页在 U* 处对每个核录一次磁带(一个内部面最多 1224 个节点),反向扫 5 次得到它的 5×30 局部 Jacobian Jf。
The residual is built from three kinds of kernel: the primitives π (5 in, 5 out per control volume), the face kernel (an interior dual face reads W and G on both sides: 30 inputs, 5 outputs), and the source kernel (15 in, 1 out). Each kernel is written once, and the same code runs on real numbers, on complex numbers, or on a “local tape”. The tape records every operation's value and its partial derivatives with respect to its one or two operands; a forward sweep gives a directional derivative, a reverse sweep the transpose. This page tapes each kernel once at U* (at most 1224 nodes for an interior face) and sweeps it backwards 5 times for its 5×30 local Jacobian Jf.
装配:同样的几遍
Assembly: the same passes
为什么这正是
Why this is exactly
链式法则:R = F(W, G) − S(W, G, d),W = π(U),G = ΓW,所以
The chain rule: R = F(W, G) − S(W, G, d), W = π(U), G = ΓW, hence
演示最后一步把循环的结果 R_d 与显式的 A·U_d 相比(A 由 120 次同样的 residual_d 逐列拼出,只为对照)。随机向量的点积检验(第 9 节)也验证了这一点:两者之差 1.6×10−16(构建页面时算的,用的是第 9 节演示打开时那一组随机向量)。
The last step of the demo compares the loop's result R_d with the explicit product A·U_d (A assembled column by column from 120 calls of this same residual_d, for the comparison only). The dot-product test on random vectors (Section 9) confirms it too: a difference of 1.6×10−16 (computed when the page was built, with the pair of random vectors the demo of Section 9 opens with).
逐步推导:原始变量的 Jacobian Π
Step by step: the Jacobian Π of the primitives
第一步,写出 π。W = π(U):ρ = U1,u = U2/U1,v = U3/U1,ν̃ = U5/U1;由 ρE = ρ(cvT + ½|u|²),
Step 1, write π out. W = π(U): ρ = U1, u = U2/U1, v = U3/U1, ν̃ = U5/U1; from ρE = ρ(cvT + ½|u|²),
第二步,逐行求导。例如 ∂T/∂U1 = (−U4/U1² + (U2² + U3²)/U1³)/cv = (u² + v² − E)/(ρcv):
Step 2, differentiate row by row. For example ∂T/∂U1 = (−U4/U1² + (U2² + U3²)/U1³)/cv = (u² + v² − E)/(ρcv):
第三步,结构。Π 是下三角矩阵,对角元 1、1/ρ、1/ρ、1/(ρcv)、1/ρ 在 ρ > 0 时都不为零,所以它可逆。前向的第 0 遍是每个控制体一次 ,伴随的最后一步是 ;ΠT 是上三角的, 的 ρ 分量收集 全部五个分量的贡献。
Step 3, the structure. Π is lower triangular, and its diagonal 1, 1/ρ, 1/ρ, 1/(ρcv), 1/ρ never vanishes for ρ > 0, so it is invertible. Pass 0 of the tangent is once per control volume, and the last step of the adjoint is ; ΠT is upper triangular, and the ρ component of gathers contributions from all five components of .
核对:在 U* 的每个控制体上,上面的 Π 与 model.js prim() 的磁带相差 2.8×10−16(相对)(本页代码在构建时计算)。
Check: in every control volume of U*, the Π above and the tape of model.js prim() differ by 2.8×10−16 (relative) (computed by this page's code at build time).
逐步推导:每一遍的前向语句
Step by step: the tangent statement of every pass
前向模式把程序的每一句 y = φ(x) 换成 ,语句的顺序不变,程序覆盖的量,前向也覆盖。下表把第 5 节 residual 的每一遍与 residual_d 的对应语句并排列出(上面演示里的清单执行的就是这组语句):左列在 U* 处取值,右列只多了点。
Forward mode replaces every statement y = φ(x) of the program by , in the same order; what the program overwrites, the tangent overwrites too. The table puts each pass of Section 5's residual next to the matching statement of residual_d (the listing of the demo above runs these statements): the left column is evaluated at U*, the right one only adds the dots.
| 遍 | pass | residual | residual_d |
|---|---|---|---|
| 0 原始变量 | 0 primitives | ||
| 1 最小二乘梯度 | 1 least-squares gradients | ||
| 2 面状态(二阶) | 2 face states (second order) | ||
| 2 面通量 | 2 face flux | ||
| 2 分发 | 2 scatter | ||
| 3 SA 源项 | 3 SA source | ||
| 4 壁面节点 | 4 wall nodes | ||
| 4 来流节点 | 4 inflow nodes |
ΔxLf = xf − xL 与 ΔxRf = xf − xR 是从两侧中心到面点的重构方向(下标从起点到终点,与最小二乘模板的 Δxij = xj − xi 一样),一阶格式 W+ = W,没有这一行。roe′、visc′ 是两个核各自的局部 Jacobian;第 8 节的 Jf 是整个面核,把重构也算在里面,所以 就是上表面状态与面通量两行合起来。壁面半面不调用任何核;来流与出口半面的核在第 9 节与它们的伴随一起推导。第 4 遍的 k 是被替换的分量:壁面节点的 ρu、ρv、ρν̃,来流节点的 ρu、ρv、ρν̃。每一句的点只作用在它读的状态上:Γ、Vi、n、r 与 d 这些几何量在这里是常数,第 12 节才对它们求导。
ΔxLf = xf − xL and ΔxRf = xf − xR are the reconstruction directions from the two centres to the face point (the subscripts run from start to end, like the stencil's Δxij = xj − xi); the first-order scheme has W+ = W and no such row. roe′ and visc′ are the two kernels' own local Jacobians; Section 8's Jf is the whole face kernel, reconstruction included, so is the table's face-states and face-flux rows together. A wall half-face calls no kernel; the kernels of the inflow and outlet half-faces are derived in Section 9 together with their adjoints. The k of pass 4 runs over the replaced components: ρu, ρv, ρν̃ of a wall node, and ρu, ρv, ρν̃ of an inflow node. Every dot acts only on the states a statement reads: the geometric quantities Γ, Vi, n, r and d are constants here, and Section 12 differentiates them.
逐步推导:Roe 核的前向语句
Step by step: the tangent statements of the Roe kernel
model.js 的 roe() 按下面九句计算一个面的对流通量(第 3 节的 Roe 推导给出了每一句的来由,第 3 节的清单是它们的缩写)。WL、WR 是两侧的面状态(二阶时是 W+),n̂ = n/|n|;n 在这里是常数。R 侧的 (1)、(2) 与 L 侧相同。
model.js's roe() computes a face's convective flux in the nine statements below (Section 3's Roe derivation gives the reason for each, and the listing of Section 3 abbreviates them). WL, WR are the two face states (W+ at second order), n̂ = n/|n|, and n is a constant here. The R side's (1) and (2) are the same as the L side's.
逐句求前向导数,就是 residual_d 在一个面上执行的语句,顺序相同:
Differentiating statement by statement gives what residual_d executes on one face, in the same order:
(3) 把 √ρ 的前向导数 代进了商的求导法则;(6) 里 。(8) 里特征向量的前向导数按它们的分量逐个加点:
(3) puts the tangent of √ρ, , into the quotient rule; in (6) . In (8) the eigenvectors' tangents take a dot on each entry:
sgn Λk 是当前解所在那一支的符号:本页是亚声速流,声波的 q̃ ∓ c̃ 离零很远,q̃ 离零多远由第 4 节列出;在那一支上 |Λk| 是光滑的(格点页一阶时,壁面节点之间的面正好在 q̃ = 0 上,见第 4 节)。粘性核的前向语句就是第 3 节粘性通量推导的第三、五、六步,SA 源项的是第 3 节 SA 源项推导的十一步;边界面的核在第 9 节。这些语句都照写成了程序(kernels_ad.js,不调用 model.js 的核,只用它的常数),下面逐项核对。
sgn Λk is the sign on the branch the solution sits on: the flow on this page is subsonic, the acoustic speeds q̃ ∓ c̃ are far from zero, and Section 4 lists how far q̃ is from it; on that branch |Λk| is smooth (on the node page at first order the faces between wall nodes sit exactly at q̃ = 0; see Section 4). The viscous kernel's tangent statements are Steps 3, 5 and 6 of Section 3's viscous-flux derivation, the SA source's the eleven steps of Section 3's SA derivation; the boundary faces' kernels are in Section 9. All these statements are also written out as a program (kernels_ad.js, which calls no kernel of model.js and uses only its constants), checked item by item below.
核对:在本页全部 48 个内部面上,沿随机方向,上面九句前向语句给出的 与 model.js roe() 的复数步长(步长 10−30)最大相对差 1.7×10−15;粘性核的前向语句 6.6×10−16;整个面核(重构、Roe 减粘性)2.5×10−15;来流半面 1.9×10−16、出口半面 5.3×10−16;两种来流处理的核在本页状态上 7.3×10−16;SA 源项(11 个控制体,连 d 一起)1.2×10−15;原始变量 4.3×10−16。把这些语句按上表拼成 residual_d,与 core.js 的 applyA(局部磁带)相差 8.6×10−16,与残差的中心差分(步长 10−6)相差 4.2×10−10(本页代码在构建时计算)。
Check: on all 48 interior faces of this page, along random directions, the of the nine tangent statements above and the complex step of model.js's roe() (step 10−30) differ by at most 1.7×10−15 (relative); the viscous kernel's tangent statements by 6.6×10−16; the whole face kernel (reconstruction, Roe minus viscous) by 2.5×10−15; the inflow half-faces by 1.9×10−16 and the outlet half-faces by 5.3×10−16; both inflow treatments' kernels at this page's state by 7.3×10−16; the SA source (11 control volumes, d included) by 1.2×10−15; the primitives by 4.3×10−16. Assembled into residual_d as in the table, the statements agree with core.js's applyA (local tapes) to 8.6×10−16 and with a central difference of the residual (step 10−6) to 4.2×10−10 (computed by this page's code at build time).
图 8.4 把这些语句放到网格上执行: 取第 10 节的前向解 v(迎角方向,),面一个接一个地把 分给两侧,源项一个接一个地加到 ρν̃ 行上,每个控制体的五个分量随之累加。扫到最后 :α 只经来流数据进入残差,所以 f 只在来流节点上不为零,其余控制体上各个面与源项的贡献相消(到求解判据 10−13)。
Figure 8.4 runs these statements on the mesh: is Section 10's tangent solution v (along the angle of attack, ), the faces one after another send to their two sides, the sources one after another add into the ρν̃ rows, and the five components of every control volume accumulate. At the end : α enters the residual only through the inflow data, so f is non-zero only at the inflow nodes, and everywhere else the faces' and sources' contributions cancel (to the solve's criterion, 10−13).
matrix-free 伴随:计算
Matrix-free adjoint mode: computing
转置一个乘积要把因子倒过来、每个因子转置。反向把第 8 节的几条语句倒过来执行,从种子 出发:
Transposing a product reverses the factors and transposes each. Reverse mode runs the statements of Section 8 backwards, from the seed :
- 面与源项的转置:原来“写 R[L]、R[R]”的地方变成“读 ”,一个 5 维权重经 JfT 变成 30 个,累加到 与 上。The transpose of the faces and the source: where R[L] and R[R] were written, is read, and one 5-vector of weights becomes 30 through JfT, accumulated into and .
- 最小二乘的转置 ΓT:前向里梯度从整个模板收集,伴随里梯度的权重送回整个模板(每个模板点加,自己减)。The transpose of the least squares, ΓT: in the tangent a gradient gathers from its whole stencil, in the adjoint the gradient's weight is sent back to its whole stencil (added at each stencil point, subtracted at its own).
- 原始变量的转置 ΠT:每个控制体一个 5×5 转置乘法,累加到 上。The transpose of the primitives, ΠT: one 5×5 transposed product per control volume, accumulated into .
- 壁面行:前向里它们在最后被覆盖,伴随里它们最先处理:权重直接加到 上,并在 中清零(),因为循环写进这些行的值从未进入结果。The wall rows: overwritten last in the tangent, handled first in the adjoint: their weights go straight into and are zeroed in (), because what the loops wrote into those rows never reached the result.
- 来流行:三行 Uk − UρW∞,k 的权重加到 上,其中 −W∞,k 倍加到 的 ρ 分量上,并在 中清零;然后能量行的权重乘 −u∞ 加到两行动量行上:这是第 4 遍里能量行组合的转置。The inflow rows: the weights of the three rows Uk − UρW∞,k go into , −W∞,k times each into the ρ component of , and are zeroed in ; then the energy row's weight, times −u∞, is added to the two momentum rows: the transpose of pass 4's energy-row combination.
点积检验
The dot-product test
取随机的 与 :如果 residual_b 真是 residual_d 的转置,第 8 节的对偶恒等式两边应在舍入误差内相等:
Take random and : if residual_b really is the transpose of residual_d, the two sides of Section 8's duality identity agree to round-off:
图 9.4 把点积检验拆开:对偶恒等式不只在两端成立,在相邻两遍之间的每一处切口都成立,因为每一遍的伴随就是它自己的转置。用上面演示打开时那一组随机向量(第 8 节引用的那一组),五处(两端与三处切口)的内积都是同一个数,也就是演示先打印的那个数。
Figure 9.4 takes the dot-product test apart: the duality identity holds not only at the two ends but at every cut between two adjacent passes, because the adjoint of every pass is its own transpose. With the pair of random vectors the demo above opens with (the pair Section 8 quotes), the inner products at all five places (the two ends and the three cuts) are the same number, the one the demo prints first.
核对:五处的内积最大相对差 6.4×10−16;两端与 core.js 的 applyA、applyAT 算出的 = 1.392、 = 1.392 一致(本页代码在构建时计算)。
Check: the five inner products differ by at most 6.4×10−16 (relative); the two ends agree with = 1.392 and = 1.392 from core.js's applyA and applyAT (computed by this page's code at build time).
逐步推导:每一遍的伴随语句(倒序、累加)
Step by step: the adjoint statement of every pass (reversed, accumulating)
反向模式把每一句 y = φ(x) 换成 ,整段程序从最后一句倒着执行;前向里覆盖了某个量的语句,在反向里先把这个量的伴随交出去,再把它清零()。下表按反向执行的顺序排列:第 4 遍最先,第 0 遍最后;每一行的右列是左列那一句的转置。
Reverse mode replaces every statement y = φ(x) by and runs the whole program backwards from its last statement; a statement that overwrote a variable first hands that variable's adjoint on and then zeroes it (). The table lists the statements in the order reverse mode runs them, pass 4 first and pass 0 last; the right column of each row is the transpose of its left column.
| 遍 | pass | residual | residual_b(按表的顺序执行) | residual_b (run in the table's order) |
|---|---|---|---|---|
| 4 来流节点 | 4 inflow nodes | |||
| 4 壁面节点 | 4 wall nodes | |||
| 3 SA 源项 | 3 SA source | |||
| 2 分发 | 2 scatter | |||
| 2 面通量 | 2 face flux | |||
| 2 面状态(二阶) | 2 face states (second order) | |||
| 1 最小二乘梯度 | 1 least-squares gradients | |||
| 0 原始变量 | 0 primitives |
累加是因为一个量被几句读到,它的伴随就要收集几份:Wi 被它自己的面状态、它所在的每个最小二乘模板、它的每个面和它自己的 SA 源项读到,所以 在这四处都有 +=。Js,i 是源项核 Visi 的局部 Jacobian(第 8 节),所以除以 Vi 与 里的 Vi 抵消。第 4 遍的反向先于一切:被替换的行在前向里最后才被覆盖,循环写进这些行的值不直接进入结果(来流节点的动量行只经能量行的组合进入,所以反向随后把 −u∞ψρE 交回这两行),所以它们的权重直接交给 并清零。
The += is there because a variable read by several statements must collect one share from each: Wi is read by its own face states, by every least-squares stencil it belongs to, by each of its faces and by its own SA source, so has a += at all four places. Js,i is the local Jacobian of the source kernel Visi (Section 8), so the division by Vi cancels the Vi in . Pass 4 reversed comes before everything: the replaced rows were overwritten last in the forward code, and what the loops wrote into them does not reach the result directly (an inflow node's momentum rows reach it only through the energy-row combination, which is why the reverse then hands −u∞ψρE back to them), so their weights go straight into and are zeroed.
逐步推导:Roe 核的伴随语句
Step by step: the adjoint statements of the Roe kernel
把第 8 节的九句倒过来:从 出发,(9) 最先、(1) 最后;每一句把它左边那个量的伴随按偏导数分给右边的每个输入,一个输入被几句读到就收集几份。跳跃的伴随 与质量通量的伴随 是中间量:(5) 把前者 + 给 R 侧、
Reverse the nine statements of Section 8: from , (9) first and (1) last; each statement shares the adjoint of its left-hand side among its inputs by the partial derivatives, and an input read by several statements collects a share from each. The jumps' adjoints and the mass flux's adjoint are intermediates: (5) sends the former to the R side with + and to the L side with −.
(3)、(2)、(1) 对 R 侧同样各有一组。(8) 的 还要按特征向量的分量送回 Roe 平均量( 是它的两个动量分量):r1、r2、r3 都给 与 ;r1,3 里的 ∓c̃n̂ 与 H̃ ∓ q̃c̃ 给 、、(上面的符号属于 k = 1);r2 的能量分量 ½(ũ² + ṽ²) 给 。按 model.js 的写法,它们与 (8) 的各行在同一段代码里完成。图 9.5 在一个面上逐句执行第 8 节的前向与这里的反向,每一句的值、点与横线都标出来。
(3), (2) and (1) have the same set for the R side. The of (8) still has to go back to the Roe averages entry by entry ( is its two momentum entries): r1, r2 and r3 all give and ; the ∓c̃n̂ and H̃ ∓ q̃c̃ of r1,3 give , and (the upper sign for k = 1); r2's energy entry ½(ũ² + ṽ²) gives . As model.js is written, these are done in the same lines as the rows of (8). Figure 9.5 runs Section 8's forward statements and these reverse ones on one face, statement by statement, with every statement's value, dot and bar.
核对:在本页 48 个内部面上,用随机的 与 ,这组伴随语句与第 8 节的前向语句满足 ,最大差 5.7×10−16(相对各乘积的绝对值之和);它们给出的 与 roe() 局部磁带的反向扫描相差 3.9×10−16(本页代码在构建时计算)。
Check: on the 48 interior faces of this page, with random and , these adjoint statements and the tangent statements of Section 8 satisfy to 5.7×10−16 (relative to the sum of the products' sizes); the they give and a reverse sweep of roe()'s local tape differ by 3.9×10−16 (computed by this page's code at build time).
逐步推导:粘性核与 SA 源项的伴随语句
Step by step: the adjoint statements of the viscous kernel and of the SA source
粘性核(第 3 节粘性通量推导的第一、二、四步,偏导数取自第三、五步)倒着执行。面通量是 Φ = roe − visc,所以从 出发;下标 ρu、ρE、ρν̃ 是 Fv 的分量,下标 L,R 表示两侧各有一句:
The viscous kernel (Steps 1, 2 and 4 of Section 3's viscous-flux derivation, with the partials of Steps 3 and 5) runs backwards. The face flux is Φ = roe − visc, so it starts from ; the subscripts ρu, ρE, ρν̃ are Fv's components, and a subscript L,R stands for one statement on each side:
第一行的 把动量行与能量行里的同一个 τn 合起来:能量行的功 uavg·τn 也读 τn。第三行来自 τn = μe[(∇fu + ∇fuT)n − ⅔tr(∇fu)n]:它对 μe 与 ∇fu 都是线性的,所以对 ∇fu 的伴随就是把 对称化,再在对角线上减去 ⅔tr()。最后一行对 φ = u、v、T、ν̃ 各一句(∇fu 的伴随的两行就是 ∇fu、∇fv 的伴随):修正梯度的转置把 Δx 方向的权重交给两个中心值,垂直方向的权重平分给两侧的梯度。
The of the first line joins the momentum rows and the energy row, whose work uavg·τn reads the same τn. The third line comes from τn = μe[(∇fu + ∇fuT)n − ⅔tr(∇fu)n], which is linear in μe and in ∇fu, so the adjoint with respect to ∇fu symmetrises and subtracts ⅔tr() on the diagonal. The last line is one statement per φ = u, v, T, ν̃ (the two rows of the adjoint of ∇fu are those of ∇fu, ∇fv): the transpose of the corrected gradient hands the weight along Δx to the two centre values and splits the weight across Δx between the two gradients.
SA 源项(第 3 节 SA 源项推导的十一步)倒着执行,从 出发。FB、FΩ、ft2′、fv2′ 与 μT 是第 3 节第一至第八步的偏导数;、 是 ∂v/∂x、∂u/∂y 在 里的分量:
The SA source (the eleven steps of Section 3's SA derivation) runs backwards from . FB, FΩ, ft2′, fv2′ and μT are the partials of Steps 1 to 8 of Section 3; and are the entries of for ∂v/∂x and ∂u/∂y:
r 被截断时它是常数 10,这一处的 不往下传。每个输入收集了几份:ν̃ 经 a、Q、r、B、χ 五处,d 经 Q、r、B 三处(第 12 节把 经壁面距离交给坐标)。前向第十一步里 −ρQ 对 ρ 的导数是 −Q − ρ∂Q/∂ρ,在这里就是第一行的 与经 χ、ν 回来的那一份。
Where r is capped it is the constant 10 and its goes no further. The shares each input collects: ν̃ through a, Q, r, B and χ, five places; d through Q, r and B, three (Section 12 hands on to the coordinates through the wall distance). The −Q − ρ∂Q/∂ρ of the forward Step 11 is here the of the first line plus the share that comes back through χ and ν.
核对:在本页 48 个内部面上,粘性核的伴随语句与它的前向语句满足点积恒等式,最大差 2.7×10−16(相对各乘积的绝对值之和),与 viscous() 局部磁带的反向扫描相差 2.8×10−16;在求源项的 11 个控制体上,SA 源项的伴随语句与前向语句 5.7×10−16,与 source() 的磁带 4.2×10−15;原始变量的 与 1.6×10−16(本页代码在构建时计算)。
Check: on the 48 interior faces of this page the viscous kernel's adjoint and tangent statements satisfy the dot-product identity to 2.7×10−16 (relative to the sum of the products' sizes) and agree with a reverse sweep of viscous()'s local tape to 2.8×10−16; in the 11 control volumes where the source is evaluated the SA source's adjoint and tangent statements to 5.7×10−16 and source()'s tape to 4.2×10−15; the primitives' and to 1.6×10−16 (computed by this page's code at build time).
逐步推导:壁面行、来流行与出口半面
Step by step: the wall rows, the inflow rows and the outlet half-faces
壁面节点。壁面半面不调用任何核(第 4 节);节点的 ρu、ρv、ρν̃ 三行被替换成 U 本身。前向 ;伴随先于一切 、:循环在这些分量上看到零,只在 ρ 与 ρE 上看到原来的权重。目标函数的 g 例外:它的种子 −eD/q∞ 正放在替换之前的动量行上(第 7 节),所以不做这一步。
The wall nodes. A wall half-face calls no kernel (Section 4); the node's ρu, ρv and ρν̃ rows are replaced by U itself. Tangent ; adjoint, before everything else, and : the loops see zero in these components and the original weights only in ρ and ρE. The objective's g is the exception: its seed −eD/q∞ sits on the momentum rows before the replacement (Section 7), so it skips this step.
来流节点。本页的残差在来流节点与来流半面上用伴随一致的处理(第 4 节);原来的版本用另一种,下面把两种一并写出,好对照。原来的处理替换 ρ、ρu、ρv、ρν̃ 四行:
The inflow nodes. This page's own residual takes the adjoint-consistent treatment on the inflow nodes and half-faces (Section 4); the original version takes the other, and both are written out below for comparison. The original treatment replaces the ρ, ρu, ρv and ρν̃ rows:
伴随一致的处理只替换三行,能量行先减去 u∞ 乘两行动量行:
The adjoint-consistent treatment replaces three rows, and the energy row first subtracts u∞ times the two momentum rows:
原来的处理转置后,循环在来流节点上只看到 (0, 0, 0, ψρE, 0):离散伴随在那里满足 λρ = 0、β = 0、φ = 0(附录 B.3),而连续伴随要的是 β + ζu = 0、φ = 0,λρ 不受约束(附录 B.2)。伴随一致的处理转置后,循环看到 (ψρ, −u∞ψρE, −v∞ψρE, ψρE, 0):动量分量加上 u∞ 乘能量分量恰为零,这一行就是离散的 β + ζu = 0(附录 B.4),而质量分量 ψρ 不受约束。来流半面的通量,原来的处理是本节点状态的对流通量减去本节点梯度给出的粘性通量(第 4 遍后只剩能量行),伴随一致的处理是 F(Wbc)·n,Wbc = (ρ∞, u∞, v∞, Ti, ν̃∞),它的前向与伴随语句是
After the original treatment's transpose the loops see only (0, 0, 0, ψρE, 0) at an inflow node: the discrete adjoint satisfies λρ = 0, β = 0 and φ = 0 there (Appendix B.3), while the continuous adjoint needs β + ζu = 0 and φ = 0 and leaves λρ free (Appendix B.2). After the adjoint-consistent treatment's transpose the loops see (ψρ, −u∞ψρE, −v∞ψρE, ψρE, 0): the momentum components plus u∞ times the energy component are exactly zero, so this row is the discrete β + ζu = 0 (Appendix B.4), and the mass component ψρ is left free. The inflow half-face's flux is, in the original treatment, the node state's convective flux minus the viscous flux of the node's gradients (only its energy row survives pass 4), and in the adjoint-consistent one F(Wbc)·n with Wbc = (ρ∞, u∞, v∞, Ti, ν̃∞), whose tangent and adjoint statements are
图 9.6 把两种处理在本页每个来流节点上的这些数并排画出来。出口半面:本节点状态的物理通量,压力换成 p∞,Φ = ρq(1, u, v, E, ν̃) + p∞(0, nx, ny, q, 0);它的前向与伴随语句与 Roe 核 (1)、(2) 在一侧的那几句相同,只是 H 换成 E、压力换成常数 p∞,能量分量多一项 p∞q(前向 )。
Figure 9.6 draws these numbers for both treatments, side by side, at every inflow node of this page. The outlet half-face: the node state's physical flux with the pressure replaced by p∞, Φ = ρq(1, u, v, E, ν̃) + p∞(0, nx, ny, q, 0); its tangent and adjoint statements are those of the Roe kernel's one-side statements (1) and (2), with H replaced by E, the pressure by the constant p∞, and the extra energy term p∞q (tangent ).
核对:来流半面 8 个、出口半面 8 个:这些伴随语句与前向语句的点积恒等式最大差 1.7×10−16,与 core.js 面核的局部磁带 JfT 相差 2.9×10−16;两种来流处理的核在本页状态上满足点积恒等式到 1.5×10−16。带强边界行的整个伴随那一遍与 core.js 的 applyAT 相差 4.6×10−16,去掉第 4 遍的版本(g 用的那个)相差 8.7×10−16;图中两种处理的行另经 core.js 核对(ATψ 等于被替换行交给 的那一份加上各遍对循环所见权重的转置)到 0(本页代码在构建时计算)。
Check: 8 inflow and 8 outlet half-faces: these adjoint statements and the tangent ones satisfy the dot-product identity to 1.7×10−16 and agree with the local tapes of core.js's face kernels, JfT, to 2.9×10−16; both inflow treatments' kernels at this page's state satisfy the identity to 1.5×10−16. The whole adjoint pass with its strong rows agrees with core.js's applyAT to 4.6×10−16, and without pass 4 (the version g uses) to 8.7×10−16; the figure's rows of both treatments are checked against core.js too (ATψ equals the replaced rows' share of plus the passes transposed on the weights the loops see) to 0 (computed by this page's code at build time).
算例:一个内部对偶面、一个壁面节点、一个来流节点
A worked example: one interior dual face, one wall node, one inflow node
用本页的数把上面的语句走一遍。前向的种子取第 10 节的前向解,(v 是第 10 节的那个向量,不是速度分量 v;迎角方向,;前向在第 195 次迭代满足判据),伴随的种子取第 11 节的伴随解,。
The statements above, walked through with this page's numbers. The tangent's seed is Section 10's tangent solution, (v is that vector, not the velocity component v; along the angle of attack, ; the tangent meets its criterion at iteration 195), and the adjoint's seed is Section 11's adjoint, .
内部面 e17(L = n9,R = n10;图 2.2 里的那个面)。两侧的原始变量、它们的前向导数,以及这个面的反向语句加给它们的伴随份额 :
The interior face e17 (L = n9, R = n10; the face of Figure 2.2). The two sides' primitives, their tangents, and the shares of their adjoints this face's reverse statements add, :
| 分量 | component | ||||||
|---|---|---|---|---|---|---|---|
| ρ | 0.6116 | 0.6232 | 0.09695 | 0.04478 | 19.87 | 12.5 | |
| u | 0.06109 | 0.6004 | −0.02033 | −0.3573 | −9.999 | 8.355 | |
| v | −0.004837 | −0.1711 | 0.05693 | 0.1228 | 5.797 | −1.736 | |
| T | 1.746 | 1.601 | −0.3298 | −0.107 | 6.688 | 4.539 | |
| ν̃ | 0.008184 | 0.02033 | −0.003148 | −0.004979 | 0.001811 | −0.004797 |
面上的通量,它的前向导数(Roe 部分与粘性部分)与种子 :
The face's flux, its tangent (the Roe part and the viscous part), and the seed :
| 分量 | component | Φ | ||||
|---|---|---|---|---|---|---|
| ρ | −0.1121 | 0.05325 | 0 | 0.05325 | 28.38 | |
| ρu | −0.4893 | 0.05123 | 5.592×10−4 | 0.05179 | −45.26 | |
| ρv | 0.319 | −0.006972 | −0.007277 | −0.01425 | 4.391 | |
| ρE | −0.6701 | 0.419 | −0.007442 | 0.4116 | 2.429 | |
| ρν̃ | −0.001014 | 9.962×10−4 | −1.209×10−5 | 9.842×10−4 | 0.04318 |
这个面上的局部对偶恒等式:两边都是 30 个输入对 5 个输出的同一个双线性型(右边依次是 WL、WR、GL、GR 四组输入的份额)。
The local duality identity on this face: both sides are the same bilinear form of 30 inputs against 5 outputs (on the right, the shares of the four groups of inputs WL, WR, GL, GR).
壁面节点 n1。它的 ρu、ρv、ρν̃ 三行被替换,所以前向解 在这三个分量上为零;伴随的第 4 遍反向把 ψ 在这三行上的值交给 ,循环只看到 ρ 与 ρE 上的权重:
The wall node n1. Its ρu, ρv and ρν̃ rows are replaced, so the tangent solution is zero in these three components; pass 4 reversed hands ψ's values in these rows to , and the loops see weights only in ρ and ρE:
| 分量 | component | 第 4 遍交给 | pass 4 to | 循环看到的 | the loops see | ||
|---|---|---|---|---|---|---|---|
| ρ | 0.1077 | 27.47 | 0 | 27.47 | |||
| ρu | 0 | −1.679 | −1.679 | 0 | |||
| ρv | 0 | −0.1425 | −0.1425 | 0 | |||
| ρE | 0.1139 | 9.735×10−4 | 0 | 9.735×10−4 | |||
| ρν̃ | 0 | −7.019×10−4 | −7.019×10−4 | 0 |
来流节点 n21(方位 180°,两种处理各在自己的收敛解上)。本页自己的解用伴随一致的处理,“一致”的两栏就是本页的 ψ 与循环看到的权重;另两栏取自另一页(原来的版本)的解。ψ 在五行上的值与第 4 遍反向之后循环看到的权重:
The inflow node n21 (at 180°, each treatment at its own converged solution). This page's own solution uses the adjoint-consistent treatment, so the “consistent” columns are this page's own ψ and the weights its loops see; the other two columns come from the solution of the original version. ψ's values in the five rows and the weights the loops see after pass 4 reversed:
| 分量 | component | 原来的 ψi | original ψi | 原来:循环看到 | original: loops see | 一致的 ψi | consistent ψi | 一致:循环看到 | consistent: loops see |
|---|---|---|---|---|---|---|---|---|---|
| ρ | 39.44 | 0 | 1117 | 1117 | |||||
| ρu | −238.4 | 0 | 51.22 | 50.86 | |||||
| ρv | 1.876 | 0 | 12.75 | 4.45 | |||||
| ρE | −32.6 | −32.6 | −215.7 | −215.7 | |||||
| ρν̃ | −0.1801 | 0 | 4.098 | 0 |
把循环看到的动量分量记作 、能量分量记作 ,两种处理的 :
Writing the momentum components the loops see as and the energy component as , the two treatments' :
(a) 是原来的处理:循环在动量分量上看到零, 就是 u∞ψρE,不为零。(b) 是伴随一致的处理:它是精确的零(u∞ = (0.2357, 0.02062))。
(a) is the original treatment: the loops see zero in the momentum components, so is u∞ψρE, not zero. (b) is the adjoint-consistent one: it is exactly zero (u∞ = (0.2357, 0.02062)).
核对:上面的前向与伴随值由 kernels_ad.js 的语句算出;用 core.js 面核的局部磁带另算一遍(Jf 乘输入的点、JfT 乘 ),两者最大相对差 1.8×10−16;内部面上对偶恒等式两边相差 1.4×10−16(相对各乘积的绝对值之和)(本页代码在构建时计算)。
Check: the tangent and adjoint values above come from the statements of kernels_ad.js; recomputed from the local tapes of core.js's face kernels (Jf times the inputs' dots, JfT times ) they differ by at most 1.8×10−16 (relative); the two sides of the duality identity on the interior face differ by 1.4×10−16 (relative to the sum of the products' sizes) (computed by this page's code at build time).
图 9.7 把伴随的各遍放到网格上倒着执行,种子取第 11 节的伴随解,(第 4 遍反向先把被替换行的权重交给 )。面倒着一个接一个,每个面把 累加到两侧;每个控制体上画的是它五个分量 的累加值, 就是 SA 变量的伴随。梯度的权重经 ΓT 回到模板,最后经 ΠT 得到 :伴随方程在每个控制体上成立,精确到求解停下时的残差:判据(残差的 RMS 小于 10−13)在第 246 次迭代首次满足,本页用的是最后一步(第 307 次)迭代,它的 RMS 是 3.3×10−14,单个分量的残差最大 2.6×10−13,所以扫描在每个控制体上留下的就是那里的 −g,差不超过这个残差;在本页这套粗网格上,目标经壁面的对偶面与它们的最小二乘模板读到全部 24 个控制体,g 处处不为零。
Figure 9.7 runs the adjoint's passes backwards on the mesh, with Section 11's adjoint as the seed, (pass 4 reversed first hands the replaced rows' weights to ). The faces go one after another in reverse, each accumulating into its two sides; every control volume shows the accumulated values of its five components , and is the adjoint of the SA variable. The gradients' weights go back to their stencils through ΓT, and finally ΠT gives : the adjoint equation holds in every control volume to the residual the solve stopped at: the criterion (an RMS residual below 10−13) was first met at iteration 246, the page uses the last iterate (iteration 307), whose RMS residual is 3.3×10−14 with a largest single entry of 2.6×10−13, so what the sweep leaves in each control volume is its −g to within that residual; on this page's coarse mesh the objective reads all 24 control volumes through the wall's dual faces and their least-squares stencils, so g is non-zero everywhere.
前向求解:A v = −f
The forward solve: A v = −f
前向方程用原始迭代的同一个 K 求解:
The tangent equation is solved with the same K as the primal iteration:
K 是 U* 处的两次对称 Gauss–Seidel(CFL 固定在 200),A v 是第 8 节的 residual_d 取 U_d = v。原始迭代在接近 U* 时的误差也按 I − KA 传播,所以两者的渐近速率相同,都是迭代矩阵 I − KA 的谱半径:二阶格式 ρ(I − KA) = 0.879(把 I − KA 装配成 120 × 120 的稠密矩阵,取它全部特征值的最大模;最大的是实特征值)。在残差从初值的 10−4 降到 10−11 的区间里拟合的每步因子是:原始 0.879、前向 0.879,与 ρ(I − KA) 的相对差 +0.0014%、
K is two symmetric Gauss–Seidel sweeps at U* (with the CFL number fixed at 200), and A v is Section 8's residual_d with U_d = v. Near U* the primal iteration's error also propagates by I − KA, so the two share the same asymptotic rate, the spectral radius of the iteration matrix I − KA: ρ(I − KA) = 0.879 for the second-order scheme (the largest modulus among all the eigenvalues of the dense 120 × 120 matrix I − KA; the largest is real). Fitted over the band where each residual falls from 10−4 to 10−11 of its start, the factors per iteration are 0.879 (primal) and 0.879 (tangent), +0.0014% and −0.0000076% from ρ(I − KA). Over a finite band the residual is not an exact geometric sequence, so a fitted factor can lie a little above or below ρ(I − KA). f = ∂R/∂D: the angle of attack and the Mach number enter only the inflow data u∞ = M√γ(cos α, sin α) (the outlet's p∞ = 1 does not depend on them); μref enters μ(T), the inflow's ν̃∞ = 3μref, and every viscous and source term.
结果:二阶格式 dCD/dα = −20.25143242、dCD/dM = −51.318265、dCD/dμref = 340.32184。它们与第 11 节伴随给出的值相对差 1.2×10−14(除以 |∂CD/∂D|、|ψTf| 与 |dCD/dD| 中最大的一个,见下);直接除以导数本身是 1.4×10−14。
The result: for the second-order scheme dCD/dα = −20.25143242, dCD/dM = −51.318265, dCD/dμref = 340.32184. They differ from the adjoint's values of Section 11 by a relative 1.2×10−14 (over the largest of |∂CD/∂D|, |ψTf| and |dCD/dD|, see below); over the derivative itself the difference is 1.4×10−14.
本页比较流动参数的导数时,相对差默认除以三个量中最大的一个:显式部分 |∂CD/∂D|、伴随部分 |ψTf|(等于前向的 |gTv|)与导数本身 |dCD/dD|。本页 dCD/dM = ∂CD/∂M + ψTf = −509.985 + 458.667 = −51.3183:两部分几乎抵消,和只有较大部分的 1/10。舍入误差随两部分的大小走,不随它们的和走,所以除以和会把它放大约 10 倍;按两部分归一量的是舍入误差真正所在的量级。第 11、13、14 节与各演示用同一个归一,并同时给出除以导数本身的值;坐标导数没有两部分之分,直接除以导数本身(或按范数,见第 14 节)。
When this page compares derivatives with respect to the flow parameters, a relative difference is by default divided by the largest of three sizes: the explicit part |∂CD/∂D|, the adjoint part |ψTf| (equal to the tangent's |gTv|) and the derivative itself |dCD/dD|. On this page dCD/dM = ∂CD/∂M + ψTf = −509.985 + 458.667 = −51.3183: the two parts nearly cancel, and the sum is 1/10 of the larger part. Round-off scales with the parts, not with their sum, so dividing by the sum inflates it about 10 times; normalising by the parts measures it at the size where it actually lives. Sections 11, 13 and 14 and the demos use the same normalisation and also give the difference over the derivative itself; the coordinate derivatives have no such parts and are divided by the derivative itself (or taken normwise, Section 14).
伴随求解:ATψ = −g
The adjoint solve: ATψ = −g
KT 不需要另外编程:在 PT 上做同样的对称扫描,正好就是 K 的转置。把 P 按控制体编号分成块对角 diag(P)、严格下三角 P< 与严格上三角 P>。从零开始的一次对称扫描(前扫接回扫)是线性算子 K1:前扫解 (diag(P) + P<)x' = b,回扫解 (diag(P) + P>)x = b − P<x',合起来
KT needs no separate code: the same symmetric sweeps on PT are exactly the transpose of K. Split P, in the numbering of the control volumes, into its block diagonal diag(P), its strictly lower block triangle P< and its strictly upper block triangle P>. One symmetric sweep from zero (forward then backward) is a linear operator K1: the forward pass solves (diag(P) + P<)x' = b, the backward pass (diag(P) + P>)x = b − P<x', and together
因为 PT 的块对角是 diag(P)T、严格下三角是 P>T、严格上三角是 P<T。本页的 K 是两次扫描:第二次从第一次的结果 x1 = K1b 出发,x2 = x1 + K1(b − Px1),所以
since the block diagonal of PT is diag(P)T, its strictly lower triangle P>T and its strictly upper triangle P<T. This page's K is two sweeps: the second starts from the first one's result x1 = K1b, x2 = x1 + K1(b − Px1), so
这正是在 PT 上做两次同样的对称扫描(扫描次数更多时同理:k 次扫描是 Σj<k(I − K1P)jK1,它的转置是 PT 上的同一个和)。代码里 precond(P, b, 2, transposed) 正是这样:transposed 时每个对角块与邻居块都取转置,扫描顺序不变。二阶格式随机向量上 ⟨a, Kb⟩ 与 ⟨KTa, b⟩ 的相对差 0(构建时测得)。于是伴随迭代与前向迭代在每一步都给出同一个导数估计:从零开始,
That is exactly two of the same symmetric sweeps on PT (and so for any number of sweeps: k sweeps are Σj<k(I − K1P)jK1, whose transpose is the same sum on PT). The code precond(P, b, 2, transposed) does just that: transposed, every diagonal and neighbour block is transposed and the sweep order stays. On random vectors ⟨a, Kb⟩ and ⟨KTa, b⟩ differ by a relative 0 for the second-order scheme (measured at build time). So the adjoint and the tangent iterations give the same derivative estimate at every iteration: started from zero,
下面的动画逐行执行一次 K 与一次 KT:两边解的行顺序相同,用到的块位置也相同,只是 PT 的第 i 行取的是 P 的第 i 列、每块转置;表里是前几步的两个导数估计。
The animation below executes one K and one KT row by row: both solve the rows in the same order and use blocks at the same places, except that row i of PT takes column i of P, every block transposed; the table gives the two derivative estimates over the first iterations.
二阶格式的实测:两者在所有迭代上的最大相对差 6.2×10−15(按第 10 节的归一;除以导数本身是 6.2×10−15)。伴随在第 246 次迭代满足判据,同一区间拟合的每步因子 0.879(与 ρ(I − KA) 相差 −0.000028%)。三个迭代(原始、前向、伴随)的渐近速率都是 ρ(I − KA) = 0.879:伴随的迭代矩阵 I − KTAT 是 I − AK 的转置,而 I − AK 与 I − KA 的谱相同。第 16 节把这个不动点迭代与 GMRES、直接 LU 分解放在一起比较。
Measured for the second-order scheme: the largest relative difference over all iterations is 6.2×10−15 (in the normalisation of Section 10; over the derivative itself 6.2×10−15). The adjoint meets its criterion at iteration 246, with a fitted factor of 0.879 over the same band (−0.000028% from ρ(I − KA)). The three iterations (primal, tangent, adjoint) share the asymptotic rate ρ(I − KA) = 0.879: the adjoint's iteration matrix I − KTAT is the transpose of I − AK, and I − AK has the spectrum of I − KA. Section 16 compares this fixed point with GMRES and a direct LU factorisation.
ψ 的每个分量是对应方程残差的灵敏度:把某个控制体某个方程的残差加上一个小量 ε(Rk → Rk + ε),CD 改变 ψkε。壁面节点被替换的行是 R = ρu − (ρu)w,边界值 (ρu)w = 0:边界值加 ε 等于残差减 ε,所以这些分量的 −ψ 就是 CD 对壁面动量边界值的灵敏度。来流节点的三行 R = Uk − UρW∞,k 也一样:−ψ 是 CD 对 UρW∞,k 这一边界值的灵敏度。来流节点的质量行与能量行是守恒平衡,它们的 ψ 与内部节点一样是场值:附录 B 把它们与连续伴随逐点比较。
Each component of ψ is the sensitivity to the residual of its equation: adding a small ε to the residual of one equation of one control volume (Rk → Rk + ε) changes CD by ψkε. A wall node's replaced row is R = ρu − (ρu)w with the boundary value (ρu)w = 0: raising the boundary value by ε lowers the residual by ε, so −ψ of these components is the sensitivity of CD to the wall's momentum boundary value. The same holds for an inflow node's three rows R = Uk − UρW∞,k: −ψ is the sensitivity of CD to the boundary value UρW∞,k. An inflow node's mass and energy rows are conservation balances, and their ψ is a field value like an interior node's: Appendix B compares them with the continuous adjoint node by node.
下面的动画把两个迭代放在一起:左边是原始的伪时间迭代从来流状态走向 U*,右边是伴随迭代从 ψ = 0 走向 ψ。伴随迭代用 U* 处的 P;原始迭代每步在当前状态重新组装 P,CFL 从 5 放大到上限 200。接近 U* 时两者的 P 相同,误差按同一个速率 ρ(I − KA) 衰减,残差曲线的斜率也就相同。
The animation below runs the two iterations side by side: on the left the primal pseudo-time iteration moves from the free stream to U*, on the right the adjoint iteration moves from ψ = 0 to ψ. The adjoint iteration uses the P at U*; the primal one reassembles P at the current state every step, with the CFL number growing from 5 to its cap of 200. Near U* the two use the same P, their errors decay at the same rate ρ(I − KA), and the residual curves have the same slope.
收敛后的 ψ 五个分量同时画在图 11.4 里(上面的演示一次只看一个)。
The five components of the converged ψ are drawn side by side in Figure 11.4 (the demo above shows one at a time).
逐步推导:一次对称扫描为什么是 x + K1(b − Px)
Step by step: why one symmetric sweep is x + K1(b − Px)
上面用了“第二次扫描从 x1 出发得到 x1 + K1(b − Px1)”。它对任何起点 x 都成立,推导如下。
Above, the second sweep from x1 was taken to give x1 + K1(b − Px1). This holds from any starting point x; here is why.
第一步,前扫。第 i 行用前面已经更新的值与后面的旧值,(diag(P) + P<)x′ = b − P>x。两边减去 (diag(P) + P<)x:
Step 1, the forward pass. Row i uses the values already updated before it and the old values after it, (diag(P) + P<)x′ = b − P>x. Subtract (diag(P) + P<)x from both sides:
第二步,回扫。同理 (diag(P) + P>)x″ = b − P<x′ 给 x″ = x′ + (diag(P) + P>)−1(b − Px′)。
Step 2, the backward pass. In the same way (diag(P) + P>)x″ = b − P<x′ gives x″ = x′ + (diag(P) + P>)−1(b − Px′).
第三步,合起来。由第一步,b − Px′ = (I − P(diag(P) + P<)−1)(b − Px);再把 I 写成 (diag(P) + P<)(diag(P) + P<)−1,并用 P = P< + diag(P) + P>:
Step 3, combine. By Step 1, b − Px′ = (I − P(diag(P) + P<)−1)(b − Px); write I as (diag(P) + P<)(diag(P) + P<)−1 and use P = P< + diag(P) + P>:
第四步,两次扫描与转置。从 x = 0 出发,x1 = K1b,x2 = x1 + K1(b − Px1) = (2K1 − K1PK1)b = Kb。转置把三个因子倒过来:K1T = (diag(P)T + P<T)−1diag(P)T(diag(P)T + P>T)−1,最右边、最先作用的 diag(P)T + P>T 正是 PT 的块对角加严格下三角:PT 上仍是先前扫、再回扫,上面的动画一行一行地演示了这一点。
Step 4, two sweeps and the transpose. From x = 0, x1 = K1b and x2 = x1 + K1(b − Px1) = (2K1 − K1PK1)b = Kb. Transposing reverses the three factors: K1T = (diag(P)T + P<T)−1diag(P)T(diag(P)T + P>T)−1, and the rightmost factor, applied first, diag(P)T + P>T, is exactly the block diagonal plus the strictly lower triangle of PT: on PT it is still a forward pass first and a backward pass second, which the animation above shows row by row.
核对:把本页的 P 写成 120×120 的稠密矩阵,由它算出的 2K1 − K1PK1 与代码的 K(对 120 个单位向量各做一次 precond)相差 5.8×10−16;transposed 扫描得到的矩阵与 KT 相差 2.9×10−16;从随机的 x 做一次扫描,与 x + K1(b − Px) 相差 1.4×10−15(都相对最大元)(本页代码在构建时计算)。
Check: with this page's P written as a dense 120×120 matrix, the 2K1 − K1PK1 computed from it and the code's K (one precond per unit vector, 120 of them) differ by 5.8×10−16; the matrix of the transposed sweeps and KT differ by 2.9×10−16; one sweep from a random x and x + K1(b − Px) differ by 1.4×10−15 (all relative to the largest entry) (computed by this page's code at build time).
几何导数:dCD/dX
Geometric derivatives: dCD/dX
坐标经几何量进入残差:面法向 n、面点 xf(重构沿 xf − xi 外推)、中心与连线 Δx、体积 V、最小二乘权重(依赖中心位置)、壁面距离(依赖中心与最近的壁面边)。ψT∂R/∂X 是固定 U* 时对残差的一次反向扫描:本页把几何那一遍也写在同一套运算上,录一条包括几何的磁带(30948 个节点),用 ψ 作种子()反向扫一次,得到 与三个流动参数的 ;同一条磁带以 再扫一次给出显式部分,两者之和就是全部 48 个坐标与 3 个流动参数的导数。
The coordinates enter the residual through the geometry: the face normals n, the face points xf (the reconstruction extrapolates along xf − xi), the centres and the lines Δx, the volumes V, the least-squares weights (which depend on the centres), and the wall distances (on the centre and the nearest wall edge). ψT∂R/∂X is one reverse sweep of the residual at fixed U*: this page writes the geometric pass on the same arithmetic, tapes the residual including the geometry (30948 nodes) and sweeps it backwards once with ψ as the seed (), which gives and, for the three flow parameters, ; one more sweep of the same tape with gives the explicit parts, and the two sums are the derivatives for all 48 coordinates and the 3 flow parameters.
不会失败的结构检验
Structural checks that cannot fail
三个恒等式只依赖离散格式的不变性,与流动无关(这里都是全导数 d):整体平移不改变任何东西,ΣidCD/dxi = ΣidCD/dyi = 0;整体旋转等价于反向转动来流,Σi(xidCD/dyi − yidCD/dxi) = −dCD/dα;长度与 μref 同时放大同一个倍数,CD(以固定参考长度 1 归一)也放大同一个倍数,ΣX·dCD/dX + μrefdCD/dμref = CD。构建页面时在 Node.js 里测得的残差:平移 1.6×10−14、旋转 3.6×10−15、伸缩 7.1×10−15;下面演示里的表是你的浏览器重算的,舍入误差不同,末位会不一样,但都在 10−13 以下。
Three identities depend only on the invariances of the discrete scheme, not on the flow (all total derivatives d here): a rigid translation changes nothing, ΣidCD/dxi = ΣidCD/dyi = 0; a rigid rotation is the same as turning the free stream the other way, Σi(xidCD/dyi − yidCD/dxi) = −dCD/dα; scaling the lengths and μref together by the same factor scales CD (normalised by the fixed reference length 1) by that factor, ΣX·dCD/dX + μrefdCD/dμref = CD. The residuals measured in Node.js when the page was built: translation 1.6×10−14, rotation 3.6×10−15, scaling 7.1×10−15; the table in the demo below is recomputed in your browser, whose round-off differs, so the last digits differ too, all below 10−13.
演示里每个箭头是移动一个节点时 CD 的变化率。只有壁面节点的移动改变物体的形状;内部与远场节点的移动只改变网格,CD 仍会变,因为离散解依赖网格。要得到对物体形状的梯度,还需要一条网格变形链:给物面形状参数 s,先把壁面的位移传给所有节点,X = X(s),再用链式法则 dCD/ds = (dCD/dX)(dX/ds)。本页只算到 dCD/dX,不含网格变形。
Each arrow of the demo is the rate of change of CD as one node moves. Only the moves of the wall nodes change the body's shape; moving an interior or far-field node changes only the mesh, and CD still changes because the discrete solution depends on the mesh. A gradient with respect to the body's shape needs a mesh-deformation chain as well: for shape parameters s of the wall, carry the wall's displacement to every node, X = X(s), and apply the chain rule dCD/ds = (dCD/dX)(dX/ds). This page stops at dCD/dX, with no mesh deformation.
流动参数的导数(演示最后一行)也是第 0 级离散问题的精确导数,但离连续问题的导数可能很远。附录 A 把格点格式加密到第 4 级:dCD/dα = −1.405,连续伴随给出 −1.416。这不是导数算错了(第 13、14 节把它核对到舍入误差),而是第 0 级网格离连续问题太远。
The derivatives with respect to the flow parameters (the demo's last line) are exact derivatives of the level-0 discrete problem too, but may be far from the continuous problem's. Appendix A refines the node scheme to level 4: dCD/dα = −1.405, and the continuous adjoint gives −1.416. The derivative is not wrong (Sections 13 and 14 check it to round-off); the level-0 mesh is simply far from the continuous problem.
逐步推导:dCD/dX 经过哪些几何量
Step by step: which geometric quantities dCD/dX passes through
第一步,几何那一遍的输出。几何那一遍把节点坐标 X 变成七个存储数组 𝒢 = (nf, xf, Δx, xi, Vi, Γij, di):面法向、面点、中心连线、中心、体积、最小二乘权重、壁面距离。残差与目标只通过它们读 X:R = R(U, 𝒢(X)),CD = CD(U, 𝒢(X))。
Step 1, the outputs of the geometric pass. The geometric pass turns the node coordinates X into seven stored arrays 𝒢 = (nf, xf, Δx, xi, Vi, Γij, di): face normals, face points, centre lines, centres, volumes, least-squares weights and wall distances. The residual and the objective read X through them only: R = R(U, 𝒢(X)), CD = CD(U, 𝒢(X)).
第二步,链式法则。固定 U*,每个数组 𝒢k 先收集它自己的伴随权重,再经几何那一遍的 Jacobian 回到 X:
Step 2, the chain rule. With U* held, each array 𝒢k first gathers its own adjoint weight, then goes back to X through the Jacobian of the geometric pass:
第三步,两次反向扫描。第一次把残差与目标录在以 𝒢 为输入的磁带上,种子是 与 ,一次得到全部 ;第二次把几何那一遍录在以 X 为输入的磁带上,分别用每个 作种子,得到它的那一份。七份之和就是第 12 节开头那一次反向扫描的结果(那里两条磁带是连在一起录的)。七份各有多大,见图 12.3。
Step 3, two reverse sweeps. The first tapes the residual and the objective with 𝒢 as the inputs and sweeps back with the seeds and , which gives every at once; the second tapes the geometric pass with X as the input and sweeps back with each as the seed, which gives that array's share. The seven shares sum to the result of the single reverse sweep at the start of Section 12 (where the two tapes are recorded as one). Figure 12.3 shows how large the seven shares are.
第四步,几个 ∂𝒢/∂X 的例子。格点页的对偶面法向由边中点与相邻单元中心的连线拼成,对偶体积是四边形碎片的鞋带面积之和,二者对坐标都是线性或双线性的;最小二乘权重见第 3 节最小二乘梯度推导的第六步,壁面距离见第 2 节壁面距离推导的第三至第五步。
Step 4, some ∂𝒢/∂X. On the node page a dual-face normal is assembled from the segments between an edge midpoint and the adjacent cell centres, and a dual volume is the sum of the shoelace areas of quadrilateral pieces, both linear or bilinear in the coordinates; the least-squares weights are Step 6 of Section 3's least-squares derivation and the wall distances Steps 3 to 5 of Section 2's wall-distance derivation.
核对:七份之和与第 12 节的 dCD/dX 相差 5.7×10−16(相对最大分量);‖dCD/dX‖ = 77.067(本页代码在构建时计算)。
Check: the seven shares sum to Section 12's dCD/dX to 5.7×10−16 (relative to the largest entry); ‖dCD/dX‖ = 77.067 (computed by this page's code at build time).
逐步推导:流动参数与几何那一遍的伴随语句
Step by step: the adjoint statements of the flow parameters and of the geometric pass
第一步,流动参数进入哪些语句。α 与 M 只进入来流数据 u∞ = M√γ(cos α, sin α);μref 进入每一次 μ(T) = μref·1.4T1.5/(T + 0.4) 与来流的 ν̃∞ = 3μref;目标自己还经 eD(α) 与 q∞ = 0.7M² 读 α 与 M。前向在这些语句上放种子 ,伴随在它们上面收集:
Step 1, which statements the flow parameters enter. α and M enter only the inflow data u∞ = M√γ(cos α, sin α); μref enters every μ(T) = μref·1.4T1.5/(T + 0.4) and the inflow's ν̃∞ = 3μref; the objective itself reads α and M through eD(α) and q∞ = 0.7M². The tangent puts its seed on these statements, and the adjoint collects on them:
与 是 的反向扫描在来流语句里收集到的来流数据的伴随,Σ 跑遍每一次 μ(T) 的求值;CL、
and are the adjoints of the inflow data that the reverse sweep with collects in the inflow statements, and the Σ runs over every evaluation of μ(T); CL, −2CD/M and ∂CD/∂μref|U are the explicit parts of Section 7. Step 2, ψTf split by the kind of statement: each kind's share by its own complex step in the parameter at this page's state, weighted by what the reverse sweep gives it there (the face loop and the sources at the weights the loops see after pass 4 reversed, pass 4's own statements at ψ):
| 参数 | parameter | 内部对偶面 | interior dual faces | 来流半面 | inflow half-faces | SA 源项 | SA sources | 第 4 遍 | pass 4 | ψTf | ∂CD/∂D | dCD/dD |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| α | 0 | −10.33 | 0 | −1.918 | −12.24 | −8.007 | −20.25 | |||||
| M | 0 | 714.2 | 0 | −255.5 | 458.7 | −510 | −51.32 | |||||
| μref | 169.7 | 0 | 0.1563 | −16.72 | 153.2 | 187.2 | 340.3 |
α 与 M 只进入读 u∞ 的语句:来流半面、第 4 遍(半面的 F(Wbc)·n;第 4 遍里能量行的组合与被替换的三行);μref 进入内部对偶面、SA 源项、第 4 遍。来流半面只在 ρν̃ 行读 ν̃∞,而这一行被第 4 遍替换,半面又没有粘性项,所以它那一格是 0。表中每一行的 ψTf 加上显式部分就是 dCD/dD。
α and M enter only the statements that read u∞: the inflow half-faces and pass 4 (the half-faces' F(Wbc)·n; pass 4's energy-row combination and three replaced rows); μref enters the interior dual faces, the SA sources and pass 4. The inflow half-faces read ν̃∞ only in the ρν̃ row, which pass 4 replaces, and have no viscous part, so their entry is 0. Each row's ψTf plus the explicit part is dCD/dD.
第三步,几何那一遍倒着执行。上一小节第三步的第一次反向扫描给出七个存储数组的伴随 ,第二次把它们沿几何那一遍的磁带送回节点坐标;这里把第二次扫描照 mesh.js geometry() 的语句逐句写出,它们是上一小节第四步那些导数的转置:
Step 3, the geometric pass backwards. The first reverse sweep of Step 3 of the previous subsection gives the adjoints of the seven stored arrays, and the second sends them back to the node coordinates along the tape of the geometric pass; here the second sweep is written out statement by statement, following mesh.js geometry(), as the transposes of the derivatives of Step 4 of the previous subsection:
对偶面法向是从边中点到两侧单元中心的各段 s 的 ±(sy, −sx) 之和,它的伴随把权重分给单元中心与边中点,单元中心再平分给单元顶点;对偶体积是四边形碎片的鞋带面积之和。第三行末的 Δxij 是最小二乘模板里的连线(到邻居节点;格点页的模板里没有壁面点),第四行的 Δx 是一个面两侧中心的连线。壁面距离那一句是第 2 节壁面距离推导第三步的转置:前向里 d 对三点的导数是 nw、
A dual-face normal is the sum of ±(sy, −sx) over the segments s from the edge midpoint to the adjacent cell centres, and its adjoint shares the weight between the cell centres and the edge midpoint, each cell centre passing its share on equally to the cell's vertices; a dual volume is the sum of the shoelace areas of quadrilateral pieces. The Δxij at the end of the third line is a least-squares stencil's line (to a neighbouring node; the node page's stencils have no wall point), the Δx of the fourth line a face's centre line. The wall-distance statement is the transpose of Step 3 of Section 2's wall-distance derivation: in forward mode d's derivatives with respect to the three points are nw, −(1 − ξ)nw and −ξnw, and reverse mode hands back with these three coefficients.
核对:三个参数的 ψTf 按语句拆开后,各格之和与整条磁带给出的 ψT∂R/∂D、与 core.js 的参数列算出的 ψTf 相差 1.7×10−15(相对各格的绝对值之和);把几何那一遍的语句照写成程序倒着执行,得到的 dCD/dX 与第 12 节一条磁带给出的相差 5.7×10−16(相对最大分量)(本页代码在构建时计算)。
Check: the three parameters' ψTf split by statement sum to the whole tape's ψT∂R/∂D and to the ψTf of core.js's parameter columns to 1.7×10−15 (relative to the sum of the entries' sizes); the geometric pass's statements written out and run backwards give Section 12's one-tape dCD/dX to 5.7×10−16 (relative to the largest entry) (computed by this page's code at build time).
前向与伴随的代价:51 对 1
The cost of the tangent and the adjoint: 51 against 1
本页的 51 个设计变量逐个用前向求导:每个设计变量先用磁带的前向扫描得到 f = ∂R/∂D,再解一次 A v = −f。图 12.4 把这 51 次求解首尾相接,横轴是与 A 的乘积次数(每次迭代一次):共 8952 次;伴随只解一次 ATψ = −g,246 次,再加两次反向扫描(ψT∂R/∂D 与 ∂CD/∂D)。两种办法给出的 51 个导数最大相对差 3.8×10−14。
This page's 51 design variables, each differentiated by the tangent: a forward sweep of the tape gives f = ∂R/∂D, then one solve of A v = −f. Figure 12.4 puts these 51 solves end to end, with the products with A on the horizontal axis (one per iteration): 8952 in all, while the adjoint solves ATψ = −g once, in 246, plus two reverse sweeps (ψT∂R/∂D and ∂CD/∂D). The 51 derivatives of the two routes differ by at most 3.8×10−14 (relative).
验证:与有限差分对照
Verification against finite differences
中心差分 [CD(D + ε) − CD(D − ε)]/(2ε) 每个设计变量要重算两次流场,每次都从 U* 出发、收敛到舍入底。步长 ε 太大,截断误差 ∝ ε²;ε 太小,重算解残留的舍入误差被 1/ε 放大。二阶格式的步长扫描(与伴随的相对差;α 一列按第 10 节的归一,另一列除以导数本身):
The central difference [CD(D + ε) − CD(D − ε)]/(2ε) re-solves the flow twice per design variable, each time from U* down to the round-off floor. With the step ε too large the truncation error ∝ ε² dominates; with ε too small the round-off left in the re-solved flows is amplified by 1/ε. The step sweep for the second-order scheme (relative difference from the adjoint; for α one column in the normalisation of Section 10 and one over the derivative itself):
| ε | α(按两部分归一) | α (over the parts) | α(除以导数本身) | α (over the derivative) | 节点 1 的 x | x of node 1 |
|---|---|---|---|---|---|---|
| 10−2 | 2.8×10−4 | 2.8×10−4 | 7.0×10−5 | |||
| 10−3 | 2.8×10−6 | 2.8×10−6 | 7.1×10−7 | |||
| 10−4 | 2.8×10−8 | 2.8×10−8 | 8.6×10−9 | |||
| 10−5 | 4.7×10−9 | 4.7×10−9 | 3.1×10−8 | |||
| 10−6 | 8.5×10−8 | 8.5×10−8 | 4.0×10−7 | |||
| 10−7 | 1.5×10−6 | 1.5×10−6 | 4.1×10−6 | |||
| 10−8 | 1.5×10−5 | 1.5×10−5 | 4.2×10−5 |
截断误差按 ε² 下降,α 在 ε = 10−5、节点 1 的 x 在 ε = 10−4 处与舍入误差相遇:最好的差分与伴随的相对差,α 为 4.7×10−9(除以导数本身 4.7×10−9),节点 1 的 x 为 8.6×10−9。最低点的具体数值取决于重算解的舍入误差,换一台机器、换一个浏览器都会略有不同(下面的演示在本机重算)。差分只能验证到这个量级;更严格的核对由复数步长(第 14 节)给出。
The truncation error falls as ε² and meets the round-off at ε = 10−5 for α and ε = 10−4 for x of node 1: the best difference agrees with the adjoint to a relative 4.7×10−9 for α (4.7×10−9 over the derivative itself) and 8.6×10−9 for x of node 1. The exact value at the minimum depends on the round-off of the re-solved flows and varies a little from machine to machine and browser to browser (the demo below re-solves here). A difference can verify no further than this; the complex step (Section 14) gives the stricter check.
复数步长
The complex step
怎样实现
How to implement it
同一份核代码换上复数算术:加减乘直接算,除法用 Smith 算法(不会溢出,虚部很小时实部与实数除法逐位相同),sqrt、exp、实数次幂取主值;|x|、min、max 与所有分支(S̃ 的两支、r 的截断、壁面距离的最近边与垂足位置、Roe 的 |Λk|)都只看实部。步长 ε = 10−30 时虚部比实部小约 30 个数量级,两个虚部的乘积小约 60 个数量级,永远碰不到实部的最后一位:每个实部都与实数代码逐位相同。
The same kernel code on complex arithmetic: addition, subtraction and multiplication as they are; division by Smith's algorithm (it never overflows, and with tiny imaginary parts its real part is bit for bit the real division); sqrt, exp and real powers on their principal branches; |x|, min, max and every branch (the two branches of S̃, the cap on r, the nearest wall edge and the foot position, Roe's |Λk|) read the real part only. With the step ε = 10−30 the imaginary parts stay about 30 orders of magnitude below the real ones and a product of two imaginary parts about 60, which never reaches the last bit of a real part: every real part is bit for bit the real code's.
从收敛的流场出发
Starting from the converged flow
把设计变量换成 D + iε,从 U* + 0i 出发,用同一个 K 迭代 U ← U − K R(U)。实部停在 U*;虚部的方程是
Replace the design variable by D + iε, start from U* + 0i, and iterate U ← U − K R(U) with the same K. The real part stays at U*; the imaginary part obeys
这正是前向迭代:Im Uk/ε 就是 vk。二阶格式前 40 次迭代上,Im CD/ε 与前向估计的最大相对差 2.5×10−15(按第 10 节的归一;除以导数本身 2.5×10−15)。收敛后复数步长与伴随的相对差:3 个流动参数 1.4×10−14(按第 10 节的归一;除以导数本身 1.9×10−14),48 个坐标(按范数:最大差除以最大导数)3.8×10−14。
This is exactly the tangent iteration: Im Uk/ε is vk. Over the first 40 iterations of the second-order scheme, Im CD/ε and the tangent estimate differ by at most 2.5×10−15 (in the normalisation of Section 10; 2.5×10−15 over the derivative itself). Once converged, the complex step agrees with the adjoint to a relative 1.4×10−14 for the 3 flow parameters (in the normalisation of Section 10; 1.9×10−14 over the derivatives themselves), and to 3.8×10−14 for the 48 coordinates (normwise: the largest difference over the largest derivative).
精度阶:制造解检验
Order of accuracy: manufactured solutions
伴随给出的是离散格式的精确导数,与格式本身几阶精度无关;格式的精度阶决定的是离散解,以及由它算出的 CD 与导数,离连续问题有多远。附录 A 的制造解只检验连续伴随的 P1 求解器;这一节检验本页的有限体积格式本身,一字不改:Roe 通量、无权最小二乘重构、SU2 式修正平均梯度的粘性通量、TMR 守恒形式的 SA(含 ft2、2012 年修正的 S̃、r ≤ 10 的截断与密度梯度项)、Sutherland 粘度,格心与格点、一阶与二阶。做法是:先选光滑的函数当精确解,由它反推出源项,再在一族逐级一致加密的网格上求解,看误差随网格尺寸按几次方减小。
The adjoint gives the exact derivative of the discrete scheme, whatever the scheme's order of accuracy; the order decides how far the discrete solution, and the CD and derivatives computed from it, are from the continuous problem. The manufactured solution of Appendix A tests only the continuous adjoint's P1 solver; this section tests the page's finite-volume scheme itself, exactly as implemented: the Roe flux, unweighted least-squares reconstruction, SU2's corrected average gradient for the viscous flux, SA in TMR's conservative form (ft2, the 2012 modified S̃, the cap r ≤ 10 and the density-gradient term included), Sutherland's viscosity; cell and node, first and second order. The method: choose smooth functions as the exact solution, derive the source that makes them one, solve on a family of uniformly refined meshes, and see by what power of the mesh size the error falls.
两个构造解
Two manufactured solutions
两个解的 ρ、u、v、T 相同,ν̃ 不同:
The two solutions share ρ, u, v and T, and differ in ν̃:
μref 取本页的 0.02。它们的涡量 ∂ve/∂x − ∂ue/∂y 在 [0.098, 0.129] 之间,处处同号,所以 Ω = |ω| 是光滑的。两个解各把 SA 的分支固定在整个区域:
μref is the page's 0.02. Their vorticity ∂ve/∂x − ∂ue/∂y lies in [0.098, 0.129], one sign everywhere, so Ω = |ω| is smooth. Each solution keeps the SA branches fixed over the whole domain:
- R(常规分支):χ 在 [0.33, 0.69],fv2 > 0,所以 B > 0,S̃ = Ω + B 处处是第一支,r ≤ 1/fv2 处处小于 10,不截断。ft2 很大(在 [0.94, 1.14]),μt/μ 很小(最大 6.5×10−4):这个解检验 fv2、ft2 与完整的 fw(r)。R (the regular branch): χ in [0.33, 0.69], fv2 > 0, so B > 0 and S̃ = Ω + B is the first branch everywhere, and r ≤ 1/fv2 stays below 10: never capped. ft2 is large (in [0.94, 1.14]) and μt/μ small (at most 6.5×10−4): this solution tests fv2, ft2 and the whole fw(r).
- M(修正分支):χ 在 [5.40, 8.60],fv2 < 0,B < −c2Ω 处处成立,S̃ 处处取 2012 年的修正分支,r 处处截断在 10。μt/μ 在 [1.65, 5.50]:涡粘性主导平均流,这个解检验 μt 对动量与能量方程的耦合。M (the modified branch): χ in [5.40, 8.60], fv2 < 0, and B < −c2Ω holds everywhere, so S̃ takes the 2012 modified branch everywhere and r is capped at 10 everywhere. μt/μ lies in [1.65, 5.50]: the eddy viscosity drives the mean flow, and this solution tests the coupling of μt into the momentum and energy equations.
余量在两处量:一处是各级网格上所有求源项的中心(第 1–5 级,两种格式),一处是整个区域里的 144720 个点(从物体中心出发的 720 条射线,每条从壁面到远场 201 个点,最近的离壁面只有间隙的万分之一)。都是正数,分支在整个区域里都没有切换:
The margins are measured in two ways: at every centre where the source is evaluated on every level (levels 1–5, both schemes), and at 144720 points over the whole domain (720 rays from the body's centre, 201 points each from the wall to the far field, the first a ten-thousandth of the gap from the wall). All are positive: no branch switches anywhere in the domain:
| 余量 | margin | R | M |
|---|---|---|---|
| S̃ 的分支:±(B + c2Ω)/Ω(区域 / 中心) | the S̃ branch: ±(B + c2Ω)/Ω (domain / centres) | 0.790 / 0.792 | 1.312 / 1.349 |
| r 的截断:±(r0 − 10)/10(区域 / 中心) | the cap on r: ±(r0 − 10)/10 (domain / centres) | 0.710 / 0.710 | 0.823 / 0.864 |
| 涡量:min|ω| / max|ω|,同号 | vorticity: min|ω| / max|ω|, one sign | 0.759 ✓ | 0.759 ✓ |
| ρ / T 的范围 | the ranges of ρ / T | 0.922–1.080 / 0.994–1.060 | 0.922–1.080 / 0.994–1.060 |
Roe 通量里的 |q̃| 是唯一避不开的不可导点:面的朝向遍布各个方向,总有面几乎与流速平行。|q̃| 只出现在耗散项里,乘的是两侧状态的跳跃(二阶 O(h²)、一阶 O(h)),它是 Lipschitz 连续的,不影响精度,只影响可导性,而这一节不求导。
Roe's |q̃| is the one kink that cannot be avoided: the faces point in every direction, and some face is always nearly parallel to the flow. |q̃| appears only in the dissipation, multiplying the jump between the two states (O(h²) at second order, O(h) at first), and it is Lipschitz: it affects differentiability, not accuracy, and this section takes no derivatives.
源项与边界
The source and the boundaries
把精确解代入第 1 节的方程,对连续通量求散度,再减去 SA 源项:
Put the exact solution into the equations of Section 1, take the divergence of the continuous fluxes, and subtract the SA source:
s 由 sympy 对解析的通量逐项求导得到(mms_gen.py),从不调用离散残差。壁面距离 d 只以代数方式进入 S,所以 s 在每个控制体中心用格式自己的 di 求值;积分用格式自己的单点规则(与 SA 源项相同),xi 是节点。sympy 的源项与本页代码的通量公式互相核对过:在任取的点上用四阶中心差分对 model.js 的通量求散度,两者在差分截断与舍入误差内一致(check_mms.js)。为了只检验内部离散,这一节把精确解加在所有边界上(core.js 的 mms 模式;本页其余各节的边界条件不变):所有边界节点的五行都替换成 U − Ue,边界半面不再调用;内部节点的最小二乘模板照常包括边界节点。
s comes from sympy differentiating the analytic fluxes term by term (mms_gen.py), never from the discrete residual. The wall distance d enters S algebraically only, so s is evaluated at every control volume's centre with the scheme's own di; the integral takes the scheme's own one-point rule (the SA source's), xi being the node. The sympy source and this page's flux formulas were checked against each other: at arbitrary points, the divergence of model.js's fluxes by fourth-order central differences agrees with the sympy source within the differences' truncation and round-off (check_mms.js). To test the interior discretisation alone, this section imposes the exact solution on every boundary (core.js's mms mode; the boundary conditions of the rest of the page are untouched): the five rows of every boundary node are replaced by U − Ue and the boundary half-faces are not called; the interior nodes' least-squares stencils include the boundary nodes as usual.
网格族与误差
The mesh family and the error
第 1–5 级网格由第 0 级逐级一致细分得到(每个三角形由三条边的中点分成 4 个,每个四边形由四条边的中点与顶点平均点分成 4 个),物面与远场都是直边八边形,每一级的计算域完全相同,网格尺寸逐级减半。误差与各自的未知量比较:格心格式的 Ui 是单元平均,与精确解守恒量的单元平均比较(每个三角形 36 点 Gauss 积分,四边形分成两个三角形);格点格式的 Ui 是节点值,与精确的节点值比较。用体积加权的 L2 范数;网格尺寸逐级减半,所以观测阶 p 就是相邻两级误差之比以 2 为底的对数。每一级都解到第 6 节的判据(先用本页的伪时间迭代 40 步,没到判据再用 Newton–GMRES 收尾),迭代误差远小于离散误差。
Levels 1–5 come from level 0 by uniform subdivision (a triangle into 4 through its edge midpoints, a quadrilateral into 4 through its edge midpoints and vertex average); the body and the far field are straight-sided octagons, so every level covers exactly the same domain and the mesh size halves from level to level. The error is measured against each scheme's own unknowns: the cell scheme's Ui is a cell average, compared with the cell average of the exact conserved variables (a 36-point Gauss rule per triangle, a quadrilateral split into two); the node scheme's Ui is a nodal value, compared with the exact nodal value. The norm is the volume-weighted L2 norm; the mesh size halves from level to level, so the observed order p is the base-2 logarithm of the ratio of the errors on neighbouring levels. Every level is solved to the criterion of Section 6 (40 steps of this page's pseudo-time iteration, then Newton–GMRES where the criterion is not met yet), so the iteration error is far below the discretisation error.
| 解 | solution | 格式 | scheme | p(ρ) | p(ρu) | p(ρv) | p(ρE) | p(ρν̃) | p(CD) |
|---|---|---|---|---|---|---|---|---|---|
| R | 格心一阶 | cell first order | 0.71 | 0.94 | 0.95 | 0.70 | 0.84 | 0.80 | |
| R | 格心二阶 | cell second order | 1.73 | 1.93 | 2.01 | 1.86 | 1.92 | (0.51) | |
| R | 格点一阶 | node first order | 0.86 | 0.87 | 0.89 | 0.82 | 0.84 | 1.02 | |
| R | 格点二阶 | node second order | 2.00 | 2.06 | 2.12 | 1.96 | 2.04 | 1.99 | |
| M | 格心一阶 | cell first order | 0.76 | 0.94 | 0.90 | 0.76 | 0.77 | 0.78 | |
| M | 格心二阶 | cell second order | 1.99 | 1.91 | 1.95 | 1.94 | 1.98 | 1.86 | |
| M | 格点一阶 | node first order | 0.69 | 0.89 | 0.91 | 0.69 | 0.70 | 0.72 | |
| M | 格点二阶 | node second order | 2.03 | 2.04 | 2.12 | 2.01 | 2.06 | 2.03 |
表中是第 4→5 级的观测阶(五个守恒分量的 L2 误差,以及目标 CD:壁面节点动量行的反作用,对精确的 eD·∮(ρu(u·n) + pn − τn)ds/q∞),各级的误差在下面的图与展开表里。CD 一栏括号里的值紧接在误差的一次变号之后,不代表收敛速率。
The table gives the observed orders from level 4 to 5 (the L2 errors of the five conserved components, and of the objective CD: the reaction of the wall nodes' momentum rows, against the exact eD·∮(ρu(u·n) + pn − τn)ds/q∞); the errors on every level are in the figure and the expandable table below. A value in brackets in the CD column comes right after a sign change of the error and does not measure a convergence rate.
展开:各级网格的 L2 误差(解 R)Expand: the L2 errors on every level (solution R)
| 格式 | scheme | 级 | level | N | ‖e(ρ)‖ | ‖e(ρu)‖ | ‖e(ρv)‖ | ‖e(ρE)‖ | ‖e(ρν̃)‖ | |CD − CD,e| |
|---|---|---|---|---|---|---|---|---|---|---|
| 格心一阶 | cell first order | 1 | 96 | 2.9×10−3 | 7.3×10−3 | 5.3×10−3 | 7.3×10−3 | 1.2×10−4 | 3.8×10−2 | |
| 格心一阶 | cell first order | 2 | 384 | 1.7×10−3 | 3.7×10−3 | 2.5×10−3 | 4.4×10−3 | 6.7×10−5 | 4.7×10−2 | |
| 格心一阶 | cell first order | 3 | 1536 | 1.0×10−3 | 1.9×10−3 | 1.2×10−3 | 2.7×10−3 | 4.0×10−5 | 3.2×10−2 | |
| 格心一阶 | cell first order | 4 | 6144 | 6.3×10−4 | 9.9×10−4 | 6.1×10−4 | 1.7×10−3 | 2.3×10−5 | 1.9×10−2 | |
| 格心一阶 | cell first order | 5 | 24576 | 3.8×10−4 | 5.2×10−4 | 3.2×10−4 | 1.0×10−3 | 1.3×10−5 | 1.1×10−2 | |
| 格心二阶 | cell second order | 1 | 96 | 5.4×10−4 | 8.4×10−4 | 7.1×10−4 | 1.6×10−3 | 2.2×10−5 | 5.8×10−3 | |
| 格心二阶 | cell second order | 2 | 384 | 1.3×10−4 | 2.0×10−4 | 1.7×10−4 | 3.7×10−4 | 7.2×10−6 | 1.4×10−3 | |
| 格心二阶 | cell second order | 3 | 1536 | 3.9×10−5 | 5.2×10−5 | 3.7×10−5 | 8.9×10−5 | 2.3×10−6 | 1.6×10−4 | |
| 格心二阶 | cell second order | 4 | 6144 | 1.2×10−5 | 1.4×10−5 | 8.6×10−6 | 2.3×10−5 | 6.5×10−7 | 4.3×10−5 | |
| 格心二阶 | cell second order | 5 | 24576 | 3.8×10−6 | 3.6×10−6 | 2.1×10−6 | 6.4×10−6 | 1.7×10−7 | 3.0×10−5 | |
| 格点一阶 | node first order | 1 | 80 | 5.0×10−3 | 8.9×10−3 | 9.4×10−3 | 1.3×10−2 | 2.0×10−4 | 3.2×10−1 | |
| 格点一阶 | node first order | 2 | 288 | 2.8×10−3 | 5.7×10−3 | 5.8×10−3 | 7.2×10−3 | 1.6×10−4 | 1.3×10−1 | |
| 格点一阶 | node first order | 3 | 1088 | 1.6×10−3 | 3.4×10−3 | 3.4×10−3 | 4.0×10−3 | 1.1×10−4 | 5.5×10−2 | |
| 格点一阶 | node first order | 4 | 4224 | 8.5×10−4 | 2.0×10−3 | 1.9×10−3 | 2.3×10−3 | 6.4×10−5 | 2.5×10−2 | |
| 格点一阶 | node first order | 5 | 16640 | 4.7×10−4 | 1.1×10−3 | 1.0×10−3 | 1.3×10−3 | 3.6×10−5 | 1.3×10−2 | |
| 格点二阶 | node second order | 1 | 80 | 1.7×10−3 | 2.6×10−3 | 1.7×10−3 | 2.9×10−3 | 5.3×10−5 | 1.9×10−1 | |
| 格点二阶 | node second order | 2 | 288 | 4.8×10−4 | 6.8×10−4 | 4.1×10−4 | 1.0×10−3 | 1.4×10−5 | 5.5×10−2 | |
| 格点二阶 | node second order | 3 | 1088 | 1.3×10−4 | 1.7×10−4 | 9.9×10−5 | 2.9×10−4 | 3.6×10−6 | 1.5×10−2 | |
| 格点二阶 | node second order | 4 | 4224 | 3.2×10−5 | 4.0×10−5 | 2.3×10−5 | 7.9×10−5 | 8.5×10−7 | 3.8×10−3 | |
| 格点二阶 | node second order | 5 | 16640 | 7.9×10−6 | 9.5×10−6 | 5.3×10−6 | 2.0×10−5 | 2.1×10−7 | 9.6×10−4 |
展开:各级网格的 L2 误差(解 M)Expand: the L2 errors on every level (solution M)
| 格式 | scheme | 级 | level | N | ‖e(ρ)‖ | ‖e(ρu)‖ | ‖e(ρv)‖ | ‖e(ρE)‖ | ‖e(ρν̃)‖ | |CD − CD,e| |
|---|---|---|---|---|---|---|---|---|---|---|
| 格心一阶 | cell first order | 1 | 96 | 4.2×10−3 | 5.7×10−3 | 3.4×10−3 | 1.1×10−2 | 4.8×10−4 | 3.0×10−1 | |
| 格心一阶 | cell first order | 2 | 384 | 3.0×10−3 | 2.8×10−3 | 1.6×10−3 | 7.8×10−3 | 3.5×10−4 | 2.3×10−1 | |
| 格心一阶 | cell first order | 3 | 1536 | 1.9×10−3 | 1.4×10−3 | 8.2×10−4 | 5.0×10−3 | 2.2×10−4 | 1.5×10−1 | |
| 格心一阶 | cell first order | 4 | 6144 | 1.2×10−3 | 7.5×10−4 | 4.4×10−4 | 3.0×10−3 | 1.4×10−4 | 9.4×10−2 | |
| 格心一阶 | cell first order | 5 | 24576 | 6.9×10−4 | 3.9×10−4 | 2.4×10−4 | 1.8×10−3 | 8.0×10−5 | 5.5×10−2 | |
| 格心二阶 | cell second order | 1 | 96 | 7.2×10−4 | 5.9×10−4 | 4.9×10−4 | 1.8×10−3 | 1.8×10−4 | 3.6×10−2 | |
| 格心二阶 | cell second order | 2 | 384 | 2.4×10−4 | 1.5×10−4 | 1.2×10−4 | 5.1×10−4 | 4.9×10−5 | 1.4×10−2 | |
| 格心二阶 | cell second order | 3 | 1536 | 7.2×10−5 | 3.9×10−5 | 2.6×10−5 | 1.5×10−4 | 1.3×10−5 | 4.7×10−3 | |
| 格心二阶 | cell second order | 4 | 6144 | 2.0×10−5 | 1.0×10−5 | 6.2×10−6 | 4.1×10−5 | 3.4×10−6 | 1.4×10−3 | |
| 格心二阶 | cell second order | 5 | 24576 | 5.0×10−6 | 2.8×10−6 | 1.6×10−6 | 1.1×10−5 | 8.6×10−7 | 3.8×10−4 | |
| 格点一阶 | node first order | 1 | 80 | 5.6×10−3 | 6.7×10−3 | 6.5×10−3 | 1.5×10−2 | 6.5×10−4 | 4.5×10−1 | |
| 格点一阶 | node first order | 2 | 288 | 3.5×10−3 | 4.0×10−3 | 3.7×10−3 | 9.4×10−3 | 4.2×10−4 | 2.6×10−1 | |
| 格点一阶 | node first order | 3 | 1088 | 2.1×10−3 | 2.3×10−3 | 2.1×10−3 | 5.8×10−3 | 2.7×10−4 | 1.6×10−1 | |
| 格点一阶 | node first order | 4 | 4224 | 1.3×10−3 | 1.3×10−3 | 1.1×10−3 | 3.6×10−3 | 1.6×10−4 | 9.9×10−2 | |
| 格点一阶 | node first order | 5 | 16640 | 8.3×10−4 | 6.8×10−4 | 6.0×10−4 | 2.2×10−3 | 1.0×10−4 | 6.0×10−2 | |
| 格点二阶 | node second order | 1 | 80 | 1.9×10−3 | 1.6×10−3 | 1.1×10−3 | 4.1×10−3 | 1.8×10−4 | 2.8×10−1 | |
| 格点二阶 | node second order | 2 | 288 | 6.0×10−4 | 4.1×10−4 | 2.5×10−4 | 1.4×10−3 | 6.1×10−5 | 8.4×10−2 | |
| 格点二阶 | node second order | 3 | 1088 | 1.7×10−4 | 1.0×10−4 | 5.7×10−5 | 4.2×10−4 | 1.7×10−5 | 2.3×10−2 | |
| 格点二阶 | node second order | 4 | 4224 | 4.3×10−5 | 2.4×10−5 | 1.3×10−5 | 1.1×10−4 | 4.4×10−6 | 5.9×10−3 | |
| 格点二阶 | node second order | 5 | 16640 | 1.1×10−5 | 5.9×10−6 | 3.0×10−6 | 2.7×10−5 | 1.1×10−6 | 1.4×10−3 |
结果
What the numbers say
- 二阶格式:五个分量的观测阶在 1.73–2.12 之间;低于 1.8 的只有解 R 上格心格式的 ρ(逐级 2.07、1.71、1.65、1.73),其余在 1.86–2.12 之间,都在 2 附近。质量方程只有对流、没有扩散;下一条说明,纯对流问题在三角形网格上的收敛阶可以低于格式的形式精度。Second order: the observed orders of the five components lie between 1.73 and 2.12; the only ones below 1.8 are the cell scheme's ρ on solution R (2.07, 1.71, 1.65, 1.73 level by level), and the rest lie between 1.86 and 2.12, all near 2. The mass equation has convection and no diffusion; the next item shows that on triangular meshes a purely convective problem can converge more slowly than the scheme's formal order.
- 一阶格式:动量分量的观测阶在 0.87–0.95 之间;密度、能量与 ρν̃ 在 0.69–0.86 之间,都明显低于 1。与前一段相比,后三者的阶变化了 −0.02 到 +0.12,有升有降,这些网格还定不下它们的渐近阶。质量方程只有对流、没有扩散;ρu、ρv、ρE、ρν̃ 的误差分别含有 u e(ρ)、v e(ρ)、E e(ρ)、ν̃ e(ρ) 一项(例如 e(ρu) ≈ u e(ρ) + ρ e(u)),除非两项相消,它们最终不会比 e(ρ) 收敛得快。纯对流问题上,迎风型格式在三角形网格上的收敛阶可以低于形式精度:Peterson(1991)构造了一族三角形网格,一阶迎风格式(零次间断 Galerkin)在其上对纯对流问题只有 h1/2。本页一阶格式的观测阶都在 1/2 与 1 之间。First order: the momentum components converge at orders between 0.87 and 0.95; the density, the energy and ρν̃ between 0.69 and 0.86, all clearly below 1. From the previous pair of levels the orders of these three changed by between −0.02 and +0.12, some rising and some falling, so these meshes do not settle their asymptotic orders. The mass equation has convection and no diffusion; the errors of ρu, ρv, ρE and ρν̃ contain the terms u e(ρ), v e(ρ), E e(ρ) and ν̃ e(ρ) (for example e(ρu) ≈ u e(ρ) + ρ e(u)), so unless the two terms cancel they cannot in the end converge faster than e(ρ). On purely convective problems an upwind-type scheme can converge on triangular meshes more slowly than its formal order: Peterson (1991) constructed a family of triangular meshes on which the first-order upwind scheme (discontinuous Galerkin of degree zero) converges only as h1/2 on a purely convective problem. At first order every observed order here lies between 1/2 and 1.
- 目标函数 CD(二阶格式):解 R 上格心格式的误差逐级为 −5.8×10−3、
−1.4×10−3、 The objective CD (second order): the cell scheme's error on solution R is −5.8×10−3, −1.4×10−3, −1.6×10−4, 4.3×10−5, 3.0×10−5 level by level, changing sign between levels 3 and 4. A sign change means that the error has at least two parts of opposite sign that shrink at different rates with h; the pair of levels across the sign change has no order, and in the pair right after it the two parts still cancel, so its observed order does not measure a convergence rate either. The observed orders between the last two levels (leaving out those affected by a sign change) lie between 1.86 and 2.03. The node scheme's reaction force comes from the discrete momentum balance itself, with measured orders 1.99 (solution R) and 2.03 (solution M).−1.6×10−4、4.3×10−5、3.0×10−5,在第 3、4 级之间变号。变号说明误差里至少有两部分符号相反、随 h 减小的快慢不同;变号的那一段没有阶,紧接着的一段里两部分仍在相消,观测阶也不代表收敛速率。最后两级的观测阶(不计受变号影响的)在 1.86–2.03 之间。格点格式的反作用力来自离散动量守恒本身,测得的阶为 1.99(解 R)与 2.03(解 M)。 - 对伴随的意义:第 8–14 节核对的是伴随给出离散 CD 的精确导数,与格式几阶无关;这一节测的是这个离散问题以多快的速度趋于连续问题。两者都是离散导数趋于连续问题导数的前提;这个收敛本身在附录 A 里直接比较。What this means for the adjoint: Sections 8–14 check that the adjoint gives the exact derivative of the discrete CD, whatever the scheme's order; this section measures how fast the discrete problem approaches the continuous one. Both are prerequisites for the discrete derivatives to approach the continuous problem's; that convergence itself is compared directly in Appendix A.
范围:这里检验的是光滑解在固定多边形区域上的内部离散。真实算例的来流与出口交界点、物面角点与不可分辨的来流薄层(附录 A.6、B.6)不在检验范围内;它们可能让真实算例收敛得比这里慢。
Scope: what is tested here is the interior discretisation on a smooth solution over a fixed polygonal domain. The junctions of inflow and outlet, the corners of the body and the unresolved inflow sublayer of the real case (Appendices A.6 and B.6) are outside the test; they can make the real case converge more slowly than the orders found here.
伴随方程的三种解法:GS、GMRES 与 LU
Three solvers for the adjoint equation: GS, GMRES and LU
第 11 节用不动点迭代 ψk+1 = ψk − KT(ATψk + g) 解伴随方程。它每步便宜(一次 AT 乘积、两次对称扫描),但收敛速率由 ρ(I − KA) 决定:本页二阶格式 ρ(I − KA) = 0.879,要 246 步才满足判据。这一节在同一个系统 ATψ = −g(120 个未知量)上比较三种解法;它们解的是同一个方程,所以给出同一个 ψ、同一组导数,差别只在怎样到达那里。
Section 11 solves the adjoint equation by the fixed point ψk+1 = ψk − KT(ATψk + g). Each step is cheap (one product with AT, two symmetric sweeps), but the rate is set by ρ(I − KA): for this page's second-order scheme ρ(I − KA) = 0.879, and the criterion takes 246 steps. This section compares three solvers on the same system ATψ = −g (120 unknowns); they solve the same equation, so they give the same ψ and the same derivatives, and differ only in how they get there.
- GS 不动点(第 11 节):沿 KT 给出的方向一步一步修正。只要 ρ(I − KA) < 1 就收敛,误差每步乘约 ρ(I − KA)。The GS fixed point (Section 11): corrections along the directions KT gives, one at a time. It converges whenever ρ(I − KA) < 1, the error shrinking by about ρ(I − KA) per step.
- GMRES,以同一个 KT 作右预处理:保存已经产生的方向 KTv0, KTv1, …,在它们张成的空间里取使残差 ‖ATψ + g‖ 最小的组合(Arnoldi 正交化加一个小最小二乘问题)。每步也是一次 AT 乘积、一次 KT,外加正交化;不需要 ρ(I − KA) < 1(不重启时,AT 与 KT 都非奇异就在 n 步内收敛)。本页每 30 步重启一次,限制存储。GMRES, right-preconditioned by the same KT: it keeps the directions produced so far, KTv0, KTv1, …, and takes the combination in their span that minimises the residual ‖ATψ + g‖ (Arnoldi orthogonalisation plus a small least-squares problem). Each step is again one product with AT and one KT, plus the orthogonalisation; it does not need ρ(I − KA) < 1 (without restarts it converges within n steps whenever AT and KT are nonsingular). This page restarts every 30 steps to bound the storage.
- 直接 LU 分解:把 AT 显式装配出来(用 120 次 residual_d 取出 A 的各列,再转置),做带部分主元的 Gauss 消元 ΠAT = LU,再做两次三角回代。没有迭代,精度只受舍入误差限制;代价是 n² = 14400 个数的存储与约 n³/3 次乘法,而且它不是 matrix-free 的。对这张 24 个控制体的网格毫无问题;每加密一级 n 约乘 4,存储约乘 16,工作量约乘 64,在实际网格上不可行。A direct LU factorisation: assemble AT explicitly (the columns of A from 120 calls of residual_d, then transposed), eliminate with partial pivoting, ΠAT = LU, and solve two triangular systems. No iteration, accuracy limited by round-off only; the price is storing n² = 14400 numbers, about n³/3 multiplications, and giving up the matrix-free form. On this mesh of 24 control volumes that is no problem at all; each level of refinement multiplies n by about 4, the storage by about 16 and the work by about 64, which rules it out on practical meshes.
构建页面时测得的结果(与 GS 不动点的导数比较;按第 10 节的归一,括号里是除以导数本身):
Measured when the page was built (derivatives compared with the GS fixed point's; in the normalisation of Section 10, over the derivatives themselves in brackets):
| 二阶格式 | second order | GS | GMRES | LU |
|---|---|---|---|---|
| 迭代步数(AT 乘积) | iterations (products with AT) | 246 | 47 (50) | — (120) |
| 最终残差 ‖ATψ + g‖(均方根) | final residual ‖ATψ + g‖ (rms) | 3.3×10−14 | 9.0×10−14 | 6.2×10−14 |
| 导数与 GS 的最大相对差 | largest relative difference of the derivatives from GS | — | 9.4×10−15 (4.5×10−14) | 1.5×10−14 (1.5×10−13) |
| 一阶格式:迭代步数 | first order: iterations | 47 | 18 | — |
三种解法给出的导数在舍入误差内相同。GMRES 的步数少得多(47 对 246),因为它不只沿最新的方向走,而是在所有已产生的方向里挑最好的组合:GS 迭代里衰减得慢、接近 ρ(I − KA) 的那几个误差分量,GMRES 几步就能把它们一起消掉。它的代价是每步的正交化与 30 个基向量的存储。LU 的装配本身就要 120 次 residual_d,比 GMRES 的 50 次乘积多,外加 O(n³) 的分解;它的用处是给迭代解法一个不依赖迭代的参照。
The three solvers give the same derivatives to round-off. GMRES needs far fewer steps (47 against 246): it does not just follow the latest direction but picks the best combination of all directions produced so far, and the few error components that the GS iteration damps slowly, near ρ(I − KA), it removes together within a few steps. Its price is the orthogonalisation per step and the storage of 30 basis vectors. LU's assembly alone takes 120 calls of residual_d, more than GMRES's 50 products, plus the O(n³) factorisation; its use is a reference for the iterative solvers that involves no iteration at all.
上面演示里的播放器把 GS 与 GMRES 的残差逐次画出来(LU 没有迭代,只在最后标出它的残差):两条线在同一个判据处停下,给出同一个 ψ。
The player of the demo above draws the GS and GMRES residuals iteration by iteration (LU has no iterations and is marked with its residual at the end): both lines stop at the same criterion and give the same ψ.
总结
Summary
| 做什么 | what | 怎样做 | how | |
|---|---|---|---|---|
residual(U) | R(U) | R(U) | 几遍循环:π、Γ、面、源项、强边界行 | passes: π, Γ, faces, source, strong rows |
residual_d(U, U_d) | 同样的几遍、同样的顺序,核换成局部 Jacobian | the same passes in the same order, kernels replaced by local Jacobians | ||
residual_b(U, R_b) | 几遍倒序,每遍转置;强边界行(壁面与来流)最先处理 | the passes reversed, each transposed; the strong rows (wall and inflow) first | ||
solve | R(U) = 0 | R(U) = 0 | 伪时间 + 两次对称块 GS(P = 一阶 Roe + 薄剪切层) | pseudo-time + two symmetric block GS sweeps (P = first-order Roe + thin shear layer) |
tangent | A v = −f | A v = −f | 同一个 K,每个设计变量一次 | the same K, once per design variable |
adjoint | ATψ = −g | ATψ = −g | KT = PT 上的同一个 SGS,一次得到全部导数 | KT = the same SGS on PT, all derivatives at once |
complex step | Im C_D / ε | Im C_D / ε | 从 U* 出发、同一个 K,虚部就是前向迭代 | from U*, the same K: the imaginary part is the tangent iteration |
FD | [C_D(D+ε) − C_D(D−ε)]/2ε | [C_D(D+ε) − C_D(D−ε)]/2ε | 每个变量两次重算,精度受步长限制 | two re-solves per variable, accuracy limited by the step |
MMS | ‖U − U_e‖ ∝ h^p | ‖U − U_e‖ ∝ h^p | 第 15 节:两个制造解、第 1–5 级网格;本页格式二阶 p = 1.96–2.12,一阶 0.69–0.91 | Section 15: two manufactured solutions, levels 1–5; this page's scheme p = 1.96–2.12 at second order, 0.69–0.91 at first |
GMRES, LU | ATψ = −g | ATψ = −g | 第 16 节:同一个方程、同一组导数;GMRES 47 步,GS 246 步 | Section 16: the same equation, the same derivatives; GMRES in 47 steps, GS in 246 |
continuous | λ = (λ_ρ, β, ζ, φ) | λ = (λ_ρ, β, ζ, φ) | 附录 A:连续伴随方程与边界条件,P1 有限元求解;加密时导数与 ψ 给出的相互靠近 | Appendix A: the continuous adjoint equations and boundary conditions, solved by P1 finite elements; under refinement its derivatives approach ψ's |
- 离散伴随只需要两样东西:每个局部核的转置(局部磁带反向扫描)和各遍的倒序。多遍结构(原始变量、梯度、面、源项)完全保留。The discrete adjoint needs only two things: the transpose of each local kernel (a reverse sweep of its local tape) and the passes in reverse order. The pass structure (primitives, gradients, faces, source) is kept entirely.
- 最小二乘让 A 的一行伸到邻居的邻居;伴随里对应的是梯度的权重回到整个模板。近似 Jacobian 只要一阶连接,Gauss–Seidel 与它的转置都只用 P。The least squares makes a row of A reach the neighbours' neighbours; in the adjoint this is a gradient's weight returning to its whole stencil. The approximate Jacobian needs first-order coupling only, and Gauss–Seidel and its transpose use P alone.
- 对称 Gauss–Seidel 的转置就是在 PT 上的同一个算法:前向与伴随在每一步给出同一个导数估计,三个迭代共用一个收敛速率。The transpose of symmetric Gauss–Seidel is the same algorithm on PT: the tangent and the adjoint give the same derivative estimate at every iteration, and the three iterations share one rate.
- 导数在当前解所在的分支上取;本页的解离所有分支点都足够远(第 4 节)。复数步长与伴随的相对差:流动参数 1.4×10−14(按第 10 节的归一;除以导数本身 1.9×10−14),48 个坐标(按范数)3.8×10−14。Derivatives are taken on the branch the solution sits on; this page's solution is far enough from every switch (Section 4). The complex step and the adjoint differ by a relative 1.4×10−14 for the flow parameters (in the normalisation of Section 10; 1.9×10−14 over the derivatives themselves), and by 3.8×10−14 (normwise) for the 48 coordinates.
- 伴随的精确性与格式的精度是两件事:第 15 节用制造解测得本页格式的阶,第 16 节说明换一种线性解法(GMRES、LU)只改变到达同一个 ψ 的路径。The exactness of the adjoint and the accuracy of the scheme are two things: Section 15 measures this page's order with manufactured solutions, and Section 16 shows that another linear solver (GMRES, LU) changes only the path to the same ψ.
- 一阶/二阶开关只改变对流通量的面状态;两种格式的伴随都用同一套代码,验证结果相同。The first/second-order switch changes only the face states of the convective flux; both schemes' adjoints run on the same code, with the same verification.
- 离散伴随是离散问题的精确导数;它是否趋于连续问题的导数是另一个问题。附录 A 推导并独立求解连续伴随:加密到第 4 级,两种离散伴随与连续伴随给出的导数相互靠近,但相邻两级之比没有稳定在 h2 的 1/4;连续问题在来流与出口交界点、物面角点上有奇性(附录 A.6)。The discrete adjoint is the exact derivative of the discrete problem; whether it approaches the derivative of the continuous problem is another question. Appendix A derives and independently solves the continuous adjoint: refined to level 4, the derivatives from the two discrete adjoints and from the continuous adjoint approach each other, though the ratio between neighbouring levels does not settle at h2's quarter; the continuous problem has singular points where the inflow meets the outlet and at the body's corners (Appendix A.6).
- 离散伴随的边界条件不是另外写的:它由原始格式在边界上的做法经转置得到。本页的来流处理使转置后的条件正是连续伴随的来流条件,所以加密时 ψ 连来流附近也趋于连续伴随(伴随一致)。附录 B 说明做法,并与原来的处理逐级比较。The discrete adjoint's boundary conditions are not written separately: they are the transpose of what the primal scheme does on the boundary. This page's inflow treatment transposes into exactly the continuous adjoint's inflow conditions, so under refinement ψ approaches the continuous adjoint near the inflow too (adjoint consistency). Appendix B explains how and compares level by level with the original treatment.
本页不涉及:限制器、激波、SA-neg。
Not on this page: limiters, shocks, SA-neg.
附录 A:连续伴随
Appendix A: the continuous adjoint
离散伴随(第 8–11 节)给出离散问题的精确导数:每一级网格用的都是同一套代码,本页网格上由点积、前向、复数步长与差分核对。连续伴随回答另一个问题:网格加密时,离散导数是否趋于连续问题的导数。本附录从第 1、4 节的连续问题出发,写出连续伴随方程、边界条件与梯度公式,用与本页离散格式无关的 P1 有限元求解(只有方程的系数取自格点格式的解,A.5),再与两种离散伴随在第 1–4 级网格上比较。方程取自二维可压缩 RANS–SA 的一份完整耦合推导(尚未公开);本附录把用到的每个公式都写出来,读者不需要那份推导稿。五个伴随方程保留标准 SA 的全部模型导数;这个问题特有的来流边界条件与对三个参数的梯度是本页补上的。
The discrete adjoint (Sections 8–11) gives the exact derivative of the discrete problem: every level runs the same code, checked on this page's mesh by the dot test, the tangent, the complex step and finite differences. The continuous adjoint answers a different question: whether the discrete derivatives approach the derivative of the continuous problem as the mesh is refined. This appendix starts from the continuous problem of Sections 1 and 4, writes out the continuous adjoint equations, boundary conditions and gradient formula, solves them by P1 finite elements, a method unrelated to this page's discrete schemes (only the equations' coefficients come from the node scheme's solution, A.5), and compares the result with both discrete adjoints on levels 1–4. The equations come from a full coupled derivation for 2-D compressible RANS–SA (not published yet); this appendix writes out every formula it uses, so the reader needs no access to that derivation. The five adjoint equations keep every model derivative of the standard SA; the inflow boundary conditions of this problem and the gradient with respect to the three parameters are added here.
A.1 连续问题
A.1 The continuous problem
区域 Ω 是第 0 级两圈八边形之间的多边形环。各级网格都在这同一个多边形上逐级细分,所以它的角点也属于连续问题。方程是第 1 节的定常 RANS–SA;边界条件是第 4 节的三种,n 指向区域外:
The domain Ω is the polygonal annulus between the two octagons of level 0. Every level refines this same polygon, so its corners belong to the continuous problem too. The equations are the steady RANS–SA of Section 1, and the boundary conditions the three kinds of Section 4, with n pointing out of the domain:
- 壁面 Γw:u = v = 0,ν̃ = 0,qn = 0(绝热);the wall Γw: u = v = 0, ν̃ = 0, qn = 0 (adiabatic);
- 来流 Γin(u∞·n < 0 的面):ρ = 1,u = u∞ = M√γ(cos α, sin α),ν̃ = 3μref,qn = 0,T 自由;the inflow Γin (the faces with u∞·n < 0): ρ = 1, u = u∞ = M√γ(cos α, sin α), ν̃ = 3μref, qn = 0, T free;
- 出口 Γout:p n − τ·n = p∞n(p∞ = 1),qn = 0,a ∂ν̃/∂n = 0。the outlet Γout: p n − τ·n = p∞n (p∞ = 1), qn = 0, a ∂ν̃/∂n = 0.
t 是流体作用在物体上的力的面密度(壁面上 n 指向物体)。设计变量 D 中的三个流动参数 m = (α, M, μref) 经来流数据 u∞(α, M)、ν̃∞ = 3μref、方向 eD(α)、动压 q∞(M) 与粘度 μ(T) = μref·1.4T1.5/(T + 0.4) 进入问题。
t is the surface density of the force the fluid exerts on the body (on the wall n points into the body). The three flow parameters of the design D, m = (α, M, μref), enter through the inflow data u∞(α, M), ν̃∞ = 3μref, the direction eD(α), the dynamic pressure q∞(M), and the viscosity μ(T) = μref·1.4T1.5/(T + 0.4).
A.2 Lagrange 函数与伴随方程
A.2 The Lagrangian and the adjoint equations
给质量、动量、能量三个守恒方程各配一个乘子 λρ、β = (β1, β2)、ζ,给单位质量形式的 SA 方程配乘子 φ,合起来记作连续伴随 λ = (λρ, β, ζ, φ):
Give the mass, momentum and energy conservation equations the multipliers λρ, β = (β1, β2) and ζ, and the SA equation, in its per-unit-mass form, the multiplier φ; together they are the continuous adjoint λ = (λρ, β, ζ, φ):
Q 是 SA 的净源项(生成减耗散,第 1 节 S5 的方括号)。第 1 节的守恒形式 SA 方程等于 ρRν̃ + ν̃Rρ,所以离散伴随里 ρν̃ 行的乘子对应 φ/ρ,ρ 行的乘子对应 λρ − ν̃φ/ρ。对状态的每个方向 δW = (δρ, δu, δT, δν̃) 求 ℒ 的一阶变分并分部积分,区域内的系数为零就是五个伴随方程。先记
Q is the SA net source (production minus destruction, the bracket of S5 in Section 1). The conservative SA equation of Section 1 equals ρRν̃ + ν̃Rρ, so in the discrete adjoint the multiplier of the ρν̃ row corresponds to φ/ρ and that of the ρ row to λρ − ν̃φ/ρ. The first variation of ℒ in every direction of the state δW = (δρ, δu, δT, δν̃), integrated by parts, has interior coefficients whose vanishing is the five adjoint equations. With
(𝒮ij = ∂jui + ∂iuj − ⅔δij∂kuk 是应变率,τ = μe𝒮;Ht 是残差对涡粘性独立变化 δμt 的反向权重),五个方程是(i = 1, 2 是两个速度方程;阻力是壁面上的目标,区域内没有源项)
(𝒮ij = ∂jui + ∂iuj − ⅔δij∂kuk is the strain rate, τ = μe𝒮; Ht is the residual's reverse weight for an independent change δμt of the eddy viscosity), the five equations are (i = 1, 2 are the two velocity equations; the drag is an objective on the wall, so there is no source in the domain)
Cν 是 SA 残差经分子运动粘度 ν = μ/ρ 反馈到流场的系数,Yω 与 𝒱 是涡量项经分部积分后的形式。a = (ν + ν̃)/σ,所以 aν̃ = aν = 1/σ。其余系数是 SA 模型函数对 ν̃、ν、Ω 的偏导数与涡粘性对状态的偏导数,全部写出如下(不冻结涡粘性,不丢密度梯度项、涡量项与 Sutherland 律)。粘度比与阻尼函数:
Cν is the SA residual's feedback into the flow through the molecular kinematic viscosity ν = μ/ρ, and Yω and 𝒱 are the vorticity term after integration by parts. a = (ν + ν̃)/σ, so aν̃ = aν = 1/σ. The remaining coefficients are the partial derivatives of the SA model functions with respect to ν̃, ν and Ω, and of the eddy viscosity with respect to the state, all written out below (the eddy viscosity is not frozen, and neither the density-gradient term, the vorticity term nor Sutherland's law is dropped). The viscosity ratio and the damping functions:
修正的涡量 S̃ = F(Ω, B) 按当地所在的分支求导:第一支 FB = FΩ = 1;第二支(B < −c2Ω)记 N = Ω(c2²Ω + c3B),Ξ = (c3 − 2c2)Ω − B,
The modified vorticity S̃ = F(Ω, B) is differentiated on the branch it sits on: on the first branch FB = FΩ = 1; on the second (B < −c2Ω), with N = Ω(c2²Ω + c3B) and Ξ = (c3 − 2c2)Ω − B,
z 依次取 ν̃、ν、Ω(δzΩ 是选择符)。r 的截断没有起作用时(r0 < 10,Ir = 1;截断时 Ir = 0),
where z runs over ν̃, ν and Ω (δzΩ selects). Where the cap on r is not active (r0 < 10, Ir = 1; capped, Ir = 0),
于是净源项 Q = cb1(1 − ft2)S̃ν̃ − Cdν̃²/d²(Cd = cw1fw − cb1ft2/κ²)的三个偏导数是
so the three partial derivatives of the net source Q = cb1(1 − ft2)S̃ν̃ − Cdν̃²/d² (Cd = cw1fw − cb1ft2/κ²) are
QΩ 既有生成项的,也有经 r → fw 传来的耗散项的导数。涡粘性 μt = ρν̃fv1(χ) 与 Sutherland 粘度的导数:
QΩ carries the derivative of the destruction through r → fw as well as that of the production. The derivatives of the eddy viscosity μt = ρν̃fv1(χ) and of Sutherland's viscosity:
所有系数都取在原始解所在的分支上:S̃ 的两支与 r ≤ 10 的截断按当地取值。这五个方程对 (λρ, β, ζ, φ) 是线性的。
Every coefficient is taken on the branch the primal solution sits on: the two branches of S̃ and the cap r ≤ 10 take their local values. The five equations are linear in (λρ, β, ζ, φ).
A.3 边界条件
A.3 Boundary conditions
分部积分留下的边界项有两部分:𝔟f 来自四个流动方程,𝔟s 来自 SA 方程:
The integration by parts leaves boundary terms in two parts: 𝔟f from the four flow equations and 𝔟s from the SA equation:
其中 𝒜 = λρ + β·u + ζE,js = a∂nν̃ 是 SA 的扩散通量,η = δν̃,b = cb2/σ。原始边界条件决定哪些变分为零、哪些自由;自由变分的系数必须为零,这就是伴随边界条件:
with 𝒜 = λρ + β·u + ζE, js = a∂nν̃ the SA diffusive flux, η = δν̃ and b = cb2/σ. The primal boundary conditions decide which variations vanish and which are free; the coefficients of the free ones must vanish, and that is the adjoint boundary condition:
| 边界 | boundary | 原始条件下的变分 | variations under the primal conditions | 伴随条件 | adjoint conditions |
|---|---|---|---|---|---|
| 壁面 | wall | δu = 0,η = 0,δqn = 0;δρ、δT、δt、δjs 自由,目标里有 eD·t/q∞ | δu = 0, η = 0, δqn = 0; δρ, δT, δt, δjs free, and the objective holds eD·t/q∞ | β = −eD/q∞,∂nζ = 0,φ = 0 | β = −eD/q∞, ∂nζ = 0, φ = 0 |
| 出口 | outlet | δt = 0,δqn = 0,δjs = 0;δρ、δu、δT、η 自由 | δt = 0, δqn = 0, δjs = 0; δρ, δu, δT, η free | 𝒜 = 0;Zn + ρun(β + ζu) + ζp∞n + Yω(ny, −nx) = 0;ke∂nζ + ρcvunζ = 0;a∂nφ + unφ = 0(出口上 js = a∂nν̃ = 0,所以 η 的系数里 −2bφ∂nν̃ 一项为零) | 𝒜 = 0; Zn + ρun(β + ζu) + ζp∞n + Yω(ny, −nx) = 0; ke∂nζ + ρcvunζ = 0; a∂nφ + unφ = 0 (js = a∂nν̃ = 0 on the outlet, so the term −2bφ∂nν̃ of η's coefficient vanishes) |
| 来流 | inflow | δρ = δu = η = 0,δqn = 0;δT、δt、δjs 自由 | δρ = δu = η = 0, δqn = 0; δT, δt, δjs free | β + ζu = 0;ke∂nζ + ρcvunζ = 0;φ = 0 | β + ζu = 0; ke∂nζ + ρcvunζ = 0; φ = 0 |
逐项看壁面一行:壁面上 u = 0,所以 un = 0,δρ 的系数 un𝒜 自动为零;δu = 0、η = 0,它们的系数不起作用。δt 自由,它的系数 β + ζu = β 加上目标里的 eD/q∞,给出 β = −eD/q∞;δT 自由,系数 ke∂nζ(un = 0)给出 ∂nζ = 0;η = 0 但 ∂nη 不受约束,所以 δjs = a∂nη 自由,它在 𝔟s 里的系数 −φ 给出 φ = 0。
The wall row term by term: u = 0 on the wall, so un = 0 and the coefficient un𝒜 of δρ vanishes by itself; δu = 0 and η = 0, so their coefficients do not matter. δt is free, and its coefficient β + ζu = β plus the objective's eD/q∞ gives β = −eD/q∞; δT is free, and its coefficient ke∂nζ (un = 0) gives ∂nζ = 0; η = 0 but ∂nη is unconstrained, so δjs = a∂nη is free, and its coefficient −φ in 𝔟s gives φ = 0.
来流一行是本页补上的。若来流给定全部五个量(T 也给定),所有状态的迹都不能变,结论是 β = ζ = φ = 0。这里 T 不给定、热流为零,所以 δT 自由而 δqn = 0;∂nδu 自由,于是 δt 可以取任意值,而且与 δT 无关(给定 δT,仍可用 ∂nδu 把 δt 调成任意值);∂nη 自由,于是 δjs 也可以。这三个自由变分在 𝔟f、𝔟s 里的系数是 β + ζu(δt)、ρcvunζ + ke∂nζ(δT)与 −φ(δjs),令它们为零就是表中的三条。ζ 满足与出口相同的 Robin 条件,β 经 β + ζu = 0 与 ζ 相连。λρ 不需要条件。伴随沿 −u 输运,所以来流边界是伴随的出口:λρ 在那里离开区域;无粘伴随在那里只接受一个条件(原始方程在来流上只有一道出射波),而粘性伴随有四个。这正是原始问题在过定出口上的情形反过来:伴随在来流边界附近有一层边界层,它的厚度就是来流线性化里向区域内增长的那个粘性模态的厚度,正面约 0.15–0.16(附录 B.6;A.6 的图可以看到它)。
The inflow row is added here. If the inflow fixed all five variables (T too), no trace of the state could vary and the result would be β = ζ = φ = 0. Here T is not prescribed and the heat flux is zero, so δT is free and δqn = 0; ∂nδu is free, so δt can take any value, independently of δT (given δT, ∂nδu can still set δt to anything); and ∂nη is free, so δjs can too. In 𝔟f and 𝔟s the coefficients of these three free variations are β + ζu (δt), ρcvunζ + ke∂nζ (δT) and −φ (δjs); setting them to zero gives the three conditions of the table. ζ satisfies the same Robin condition as at the outlet, and β is tied to ζ by β + ζu = 0. λρ takes no condition. The adjoint is transported along −u, so the inflow is the adjoint's outlet: λρ leaves the domain there, and the inviscid adjoint accepts only one condition there (the primal has only one outgoing wave at the inflow), while the viscous adjoint has four. This is the primal problem's over-specified outlet turned around: the adjoint carries a boundary layer next to the inflow, as thick as the viscous mode of the inflow's linearisation that grows into the domain, about 0.15–0.16 on the front faces (Appendix B.6; visible in the figure of A.6).
A.4 梯度
A.4 The gradient
参数变化时状态 W(m) 仍满足边界条件,但来流上的数据变了:δu = ∂u∞/∂m,η = ∂ν̃∞/∂m;其余变分(δT、δt、δjs)的系数已由伴随条件置零。代入 𝔟f、𝔟s,一个伴随解给出三个导数:
As a parameter changes, the state W(m) keeps satisfying the boundary conditions, but the data on the inflow change: δu = ∂u∞/∂m and η = ∂ν̃∞/∂m, while the coefficients of the other variations (δT, δt, δjs) have been set to zero by the adjoint conditions. Put into 𝔟f and 𝔟s, one adjoint solution gives all three derivatives:
在来流上 φ = 0,所以 Yω 与 η 系数里含 φ 的项都消失。第一项是目标的显式导数:α 经 eD(α),∂CD/∂α|W = eD′·F/q∞(F 是物体受的力,eD′ = (−sin α, cos α));M 经 q∞,∂CD/∂M|W = −2CD/M。μref 也经 t 里的粘性应力进入目标,但这一项与壁面边界项 (β + ζu)·δt 在 β = −eD/q∞ 时正好抵消(来流上 β + ζu = 0 让同类的项为零,出口的牵引力是给定值),所以对 μref 第一项为零,剩下来流上的 a∂nφ ∂ν̃∞/∂μref(ν̃∞ = 3μref)与最后的体积分,体积分里的偏导数在固定状态下取(第 4 级上两者分别是 13.37 与 207.00)。体积分只对 μref 非零:α 与 M 只经来流速度进入问题。
On the inflow φ = 0, so Yω and the terms with φ in η's coefficient drop out. The first term is the objective's explicit derivative: α enters through eD(α), ∂CD/∂α|W = eD′·F/q∞ (F the force on the body, eD′ = (−sin α, cos α)); M through q∞, ∂CD/∂M|W = −2CD/M. μref also enters the objective through the viscous stress in t, but that term cancels exactly against the wall's boundary term (β + ζu)·δt at β = −eD/q∞ (on the inflow β + ζu = 0 removes the same kind of term, and the outlet's traction is prescribed), so for μref the first term is zero; what remains is the inflow term a∂nφ ∂ν̃∞/∂μref (ν̃∞ = 3μref) and the last volume integral, whose partial derivatives are taken at a fixed state (on level 4 they are 13.37 and 207.00). The volume integral is non-zero for μref only: α and M enter the problem only through the inflow velocity.
A.5 离散:P1 有限元
A.5 Discretisation: P1 finite elements
连续伴随用与第 3–11 节无关的办法求解:每一级网格的四边形沿一条对角线分成两个三角形,五个伴随场都取连续分片线性函数(P1),用 Galerkin 弱形式;方程的系数取格点格式在同一级网格上收敛解的 P1 插值。
The continuous adjoint is solved by a method unrelated to Sections 3–11: every quadrilateral of a level is split into two triangles along a diagonal, the five adjoint fields are continuous and piecewise linear (P1), and the weak form is Galerkin; the coefficients come from the P1 interpolant of the node scheme's converged solution on the same level.
- 二阶项(∇·Z、∇·(ke∇ζ)、∇·(a∇φ)、∇·(φ∇ν̃))与涡量项 𝒱 分部积分到试函数上,所以只用到原始解的一阶导数,sgn ω 的跳跃也精确保留;the second-order terms (∇·Z, ∇·(ke∇ζ), ∇·(a∇φ), ∇·(φ∇ν̃)) and the vorticity term 𝒱 are integrated by parts onto the test function, so only first derivatives of the primal solution appear, and the jump of sgn ω is kept exactly;
- 稳定化:内部边上的连续内罚 ciphF2 s∫F[∂nw][∂nλ] ds(λρ、β、ζ 取 s = |u·n| + c,φ 取 s = |u·n|,cip = 0.05)。光滑解的法向导数在边上没有跳跃,所以这一项是相容的;stabilisation: the continuous interior penalty ciphF2 s∫F[∂nw][∂nλ] ds on the interior edges (s = |u·n| + c for λρ, β, ζ and s = |u·n| for φ, cip = 0.05). A smooth solution's normal derivative has no jump across an edge, so this term is consistent;
- 边界:强条件在节点上直接替换方程——壁面 β = −eD/q∞、φ = 0;来流 β + ζu = 0、φ = 0;出口 𝒜 = 0(替换 λρ 的方程)。自然条件进入弱形式:出口的动量与能量 Robin 项,来流的能量 Robin 项;boundaries: the strong conditions replace equations at the nodes: β = −eD/q∞ and φ = 0 on the wall, β + ζu = 0 and φ = 0 on the inflow, and 𝒜 = 0 on the outlet (replacing λρ's equation). The natural conditions enter the weak form: the outlet's momentum and energy Robin terms, and the inflow's energy Robin term;
- 梯度里的 Zn 与 a∂nφ 不从 λ 的离散边界导数求,而是变分地取:把 ∂u∞/∂m、∂ν̃∞/∂m 放在来流节点上的试函数代入未加强条件的弱形式;the Zn and a∂nφ of the gradient are not taken from the discrete λ's derivative on the boundary but variationally: a test function carrying ∂u∞/∂m and ∂ν̃∞/∂m at the inflow nodes is put into the weak form before the strong conditions are imposed;
- 线性方程组用稀疏 LU 直接求解。有限体积格式的 A 与 AT 都没有用到——这是两种伴随的比较有意义的前提。the linear system is solved directly by sparse LU. Neither the finite-volume schemes' A nor AT is used anywhere: that is what makes the comparison of the two adjoints meaningful.
A.6 验证
A.6 Verification
方程。弱形式的系数数组写成强形式后,与一个独立实现的强形式比较(它用自己的多项式原始场与乘子,按 A.2 的五个方程直接用 LGL 谱微分求值,阶数 12、20、28):最大相对差 3.0×10−14。两边的 SA 模型函数与它们的偏导数取自同一个函数,所以这一项检验的是方程的组装,不单独检验这些偏导数。
The equations. The weak form's coefficient arrays, written in strong form, are compared with an independent implementation of the strong form (on its own polynomial primal fields and multipliers, evaluating the five equations of A.2 directly with LGL spectral differentiation of orders 12, 20, 28): the largest relative difference is 3.0×10−14. Both take the SA model functions and their partial derivatives from the same routine, so this checks how the equations are assembled, not those partials on their own.
离散。给定解析的原始场、壁面距离与伴随场,把强形式代入得到源项与边界数据,在第 2–5 级网格上求解(制造的场让每个 SA 分支都不切换)。五个分量的 L2 误差:
The discretisation. Given analytic primal fields, wall distance and adjoint fields, the strong form gives the source terms and boundary data, and the problem is solved on levels 2–5 (the manufactured fields keep every SA branch from switching). The L2 errors of the five components:
| 级 | level | h | λρ | β1 | β2 | ζ | φ |
|---|---|---|---|---|---|---|---|
| 2 | 0.1909 | 7.5×10−3 | 3.5×10−3 | 3.4×10−3 | 2.4×10−3 | 8.9×10−4 | |
| 3 | 0.0955 | 1.5×10−3 | 9.3×10−4 | 8.4×10−4 | 4.3×10−4 | 2.0×10−4 | |
| 4 | 0.0477 | 3.3×10−4 | 2.3×10−4 | 2.1×10−4 | 8.4×10−5 | 4.8×10−5 | |
| 5 | 0.0239 | 7.9×10−5 | 5.8×10−5 | 5.2×10−5 | 1.8×10−5 | 1.2×10−5 | |
| 阶 | order | 2.06 | 2.00 | 2.00 | 2.20 | 2.04 |
最后一行是第 4→5 级的阶:都接近 P1 的 2。梯度用到的两个来流泛函也收敛:对流项 ∫(ρ𝒜n + ζt + …)·δu 的相对误差依次为 1.7×10−3、3.7×10−4、8.7×10−5、2.0×10−5;变分取得的通量项 ∫(Zn·δu + a∂nφ δν̃) 依次为 3.1×10−3、2.6×10−4、4.9×10−6、1.4×10−5。这一项只检验连续伴随的 P1 求解器;本页有限体积格式本身的精度阶在第 15 节。
The last row is the order from level 4 to 5: all close to P1's 2. The two inflow functionals of the gradient converge as well: the convective term ∫(ρ𝒜n + ζt + …)·δu with relative errors 1.7×10−3, 3.7×10−4, 8.7×10−5, 2.0×10−5, and the variationally recovered flux term ∫(Zn·δu + a∂nφ δν̃) with 3.1×10−3, 2.6×10−4, 4.9×10−6, 1.4×10−5. This tests the continuous adjoint's P1 solver only; the order of accuracy of this page's finite-volume scheme itself is in Section 15.
连续与离散。同一个连续问题的三种近似:格点、格心两种离散伴随(第 11 节的伴随方程,用第 16 节的 GMRES 求解:较细的格心网格上第 11 节的不动点迭代发散;各级网格上都是离散问题的精确导数)与上面的连续伴随(系数取格点格式的解)。CD 与三个导数随网格加密:
Continuous and discrete. Three approximations of the same continuous problem: the node and cell discrete adjoints (the adjoint equation of Section 11, solved by the GMRES of Section 16, since on the finer cell meshes the fixed point of Section 11 diverges; on every level the exact derivative of the discrete problem) and the continuous adjoint above (its coefficients from the node scheme's solution). CD and the three derivatives under refinement:
| 级 | level | 格点 CD | node CD | 格心 CD | cell CD |
|---|---|---|---|---|---|
| 0 | 50.9985 | 5.9162 | |||
| 1 | 11.3766 | 6.2830 | |||
| 2 | 7.2709 | 6.4102 | |||
| 3 | 6.6062 | 6.4429 | |||
| 4 | 6.4560 | 6.4138 |
| 级 | level | 连续伴随 dCD/dα | continuous dCD/dα | 格点离散伴随 | node discrete | 格心离散伴随 | cell discrete |
|---|---|---|---|---|---|---|---|
| 0 | — | −20.2514 | −1.3204 | ||||
| 1 | −5.0102 | −2.7678 | −1.1632 | ||||
| 2 | −1.8817 | −1.5413 | −1.1402 | ||||
| 3 | −1.4974 | −1.4312 | −1.2654 | ||||
| 4 | −1.4158 | −1.4049 | −1.3258 |
| 级 | level | 连续伴随 dCD/dM | continuous dCD/dM | 格点离散伴随 | node discrete | 格心离散伴随 | cell discrete |
|---|---|---|---|---|---|---|---|
| 0 | — | −51.3183 | −15.2557 | ||||
| 1 | 30.0102 | −26.4596 | −15.3531 | ||||
| 2 | −6.0046 | −15.4155 | −13.1051 | ||||
| 3 | −10.9820 | −13.0715 | −12.5009 | ||||
| 4 | −12.1130 | −12.6740 | −12.4496 |
| 级 | level | 连续伴随 dCD/dμref | continuous dCD/dμref | 格点离散伴随 | node discrete | 格心离散伴随 | cell discrete |
|---|---|---|---|---|---|---|---|
| 0 | — | 340.32 | 158.76 | ||||
| 1 | 321.36 | 287.63 | 196.30 | ||||
| 2 | 250.43 | 236.40 | 209.35 | ||||
| 3 | 226.18 | 222.67 | 212.92 | ||||
| 4 | 220.38 | 219.00 | 214.62 |
连续伴随与本页(格点)离散伴随给出的导数的相对差(除以格点值,第 1、2、3、4 级):α −81.0% → −22.1% → −4.6% → −0.8%;M 213.4% → 61.0% → 16.0% → 4.4%;μref 11.7% → 5.9% → 1.6% → 0.6%。相邻两级之比:α 0.27、0.21、0.17;M 0.29、0.26、0.28;μref 0.51、0.27、0.40。从第 1 级到第 4 级,三个差分别缩小到原来的 1/104、1/48、1/19,但相邻两级之比没有稳定在 h2 的 1/4;最后一步比前一步慢的是 M、μref,α 的最后一步最快。第 4 级:格心离散伴随给出 −1.326、
The relative difference between the derivatives from the continuous adjoint and from this page's (node) discrete adjoint (over the node value, levels 1, 2, 3, 4): α −81.0% → −22.1% → −4.6% → −0.8%; M 213.4% → 61.0% → 16.0% → 4.4%; μref 11.7% → 5.9% → 1.6% → 0.6%. The ratios between neighbouring levels: α 0.27, 0.21, 0.17; M 0.29, 0.26, 0.28; μref 0.51, 0.27, 0.40. From level 1 to level 4 the three differences shrink by factors of 104, 48, 19, but the ratio between neighbouring levels does not settle at a quarter (h2); the last step is slower than the one before for M, μref, while for α the last step is the fastest. On level 4 the cell scheme's discrete adjoint gives −1.326, −12.450, 214.6, this page's (node) −1.405, −12.674, 219.0. The two schemes' relative differences from the continuous adjoint on level 4: cell α 6.8%, M 2.7%, μref 2.7%, node α 0.8%, M 4.4%, μref 0.6%; the cell scheme lies further away for α, μref and closer for M. The continuous adjoint takes its coefficients from the node scheme's solution, which the node discrete adjoint shares; the cell scheme's comparison also carries the difference between the two schemes' primal solutions (CD on level 4: cell 6.4138, node 6.4560), and on the two side faces its row of cells along the boundary carries too little density (Appendix B.6); the dashed lines are the difference between the two discrete adjoints. Why the ratio does not settle lies in the continuous problem itself: at the two octagon vertices where the inflow meets the outlet, the velocity's Dirichlet condition meets the traction condition, and on the outlet side the velocity deviation |u − u∞| varies as a power of the distance to the vertex (fitted at the two junctions on level 4: powers 0.65, 0.67, below 1), so the solution's gradient is unbounded there; the corners of the body's octagon are singular points too. Near these points neither the primal solution nor the adjoint is smooth, and the discretisation error there does not follow a smooth solution's h2 law. Besides, the continuous adjoint carries the inflow boundary layer of A.3, which the P1 solution has to resolve on the mesh.
伴随场本身。格点格式的残差第 i 行是守恒残差在节点 i 的对偶体上的积分,本页的 Lagrange 函数是 CD + ψTR,与 A.2 的 ℒ 同号,所以 ψi 近似连续伴随在 xi 处的守恒方程乘子(A.2)。边界节点(壁面、来流、出口)不参加比较:强条件行的 ψ 是反作用。离来流边界 0.8 以外的节点上,两者的相对均方根差:
The adjoint fields themselves. Row i of the node scheme's residual is the integral of the conservative residual over node i's dual cell, and this page's Lagrangian CD + ψTR has the sign of A.2's ℒ, so ψi approximates the continuous adjoint's multipliers of the conservative equations at xi (A.2). The boundary nodes (wall, inflow, outlet) are left out: the ψ of a strong row is a reaction. Over the nodes farther than 0.8 from the inflow, the relative RMS difference of the two:
| 级 | level | ψρ ↔ λρ − ν̃φ/ρ | ψρu ↔ β1 | ψρv ↔ β2 | ψρE ↔ ζ | ψρν̃ ↔ φ/ρ |
|---|---|---|---|---|---|---|
| 2 | 96.8% | 16.6% | 21.1% | 34.3% | 17.7% | |
| 3 | 17.2% | 5.0% | 6.3% | 7.5% | 6.7% | |
| 4 | 12.7% | 1.3% | 2.0% | 5.7% | 2.0% |
动量与 ν̃ 的乘子逐级靠近(第 3→4 级之比 0.27–0.31);质量与能量的乘子收敛得慢一些,它们与来流边界层和出口的 𝒜 = 0 耦合在一起。靠近来流,连续伴随有 A.3 所说的边界层(ζ 与 λρ 向来流陡升;附录 B.6 的线性化给出它在正面的厚度约 0.15–0.16)。本页的格点离散伴随随加密也趋于这一层:来流处理转置后给出的正是 A.3 的来流条件,这就是伴随一致(附录 B 逐级比较两种处理)。
The multipliers of momentum and ν̃ approach each other level by level (a ratio of 0.27–0.31 from level 3 to 4); those of mass and energy converge more slowly, being coupled to the inflow layer and to the outlet's 𝒜 = 0. Near the inflow the continuous adjoint has the boundary layer of A.3 (ζ and λρ climb steeply towards the inflow; the linearisation of Appendix B.6 gives it a thickness of about 0.15–0.16 on the front faces). This page's node discrete adjoint approaches this layer too under refinement: its inflow treatment transposes into exactly the inflow conditions of A.3, which is adjoint consistency (Appendix B compares the two treatments level by level).
结论:离散伴随在每一级都是离散问题的精确导数(第 13、14 节);连续伴随是对连续问题导数的另一种近似。从第 1 级到第 4 级,两者的差缩小到原来的 1/104、1/48、1/19(α、M、μref):这是数值上的证据,说明本页的两种离散格式与这个连续问题相容,它们的导数趋于同一个连续灵敏度。
The conclusion: on every level the discrete adjoint is the exact derivative of the discrete problem (Sections 13 and 14), and the continuous adjoint is another approximation of the continuous problem's derivative. From level 1 to level 4 the difference between them shrinks by factors of 104, 48, 19 (α, M, μref): numerical evidence that this page's two discrete schemes are consistent with this continuous problem and that their derivatives approach the same continuous sensitivity.
范围:这里比较的是同一个连续问题(包括它的角点)的几种近似,结论是数值上的。它不证明连续问题解的存在唯一与伴随的正则性;在交界点与角点附近,伴随与原始解一样有奇性,在 ω = 0 或 r0 = 10 处模型本身不可微,那里需要单侧导数(S̃ 两支交界处一阶导数连续)。连续伴随的系数取自格点格式的解,所以它检验的是伴随方程、边界条件与梯度公式,不单独检验原始解。
Scope: what is compared here are several approximations of the same continuous problem (its corners included), and the conclusion is numerical. It does not prove existence and uniqueness for the continuous problem or the regularity of its adjoint; near the junctions and the corners the adjoint is singular like the primal solution, and where ω = 0 or r0 = 10 the model itself is not differentiable and needs one-sided derivatives (the two branches of S̃ meet with a continuous first derivative). The continuous adjoint takes its coefficients from the node scheme's solution, so it tests the adjoint equations, boundary conditions and gradient formula, not the primal solution on its own.
参考文献
References
- P. R. Spalart, S. R. Allmaras, A one-equation turbulence model for aerodynamic flows, La Recherche Aérospatiale 1 (1994) 5–21。标准 SA 模型。P. R. Spalart, S. R. Allmaras, A one-equation turbulence model for aerodynamic flows, La Recherche Aérospatiale 1 (1994) 5–21. The standard SA model.
- S. R. Allmaras, F. T. Johnson, P. R. Spalart, Modifications and clarifications for the implementation of the Spalart–Allmaras turbulence model, ICCFD7-1902 (2012)。S̃ 的修正分支与可压缩守恒形式里的密度梯度项。S. R. Allmaras, F. T. Johnson, P. R. Spalart, Modifications and clarifications for the implementation of the Spalart–Allmaras turbulence model, ICCFD7-1902 (2012). The modified branch of S̃ and the density-gradient term of the compressible conservative form.
- NASA Langley Turbulence Modeling Resource(TMR),The Spalart–Allmaras turbulence model,turbmodels.larc.nasa.gov。本页所用的标准 SA(含 ft2、r ≤ 10)与常数。NASA Langley Turbulence Modeling Resource (TMR), The Spalart–Allmaras turbulence model, turbmodels.larc.nasa.gov. The standard SA used here (with ft2 and r ≤ 10) and its constants.
- P. L. Roe, Approximate Riemann solvers, parameter vectors, and difference schemes, J. Comput. Phys. 43 (1981) 357–372。Roe 通量。P. L. Roe, Approximate Riemann solvers, parameter vectors, and difference schemes, J. Comput. Phys. 43 (1981) 357–372. The Roe flux.
- T. D. Economon, F. Palacios, S. R. Copeland, T. W. Lukaczyk, J. J. Alonso, SU2: an open-source suite for multiphysics simulation and design, AIAA J. 54 (2016) 828–846。边式格点格式与修正平均梯度的粘性通量。T. D. Economon, F. Palacios, S. R. Copeland, T. W. Lukaczyk, J. J. Alonso, SU2: an open-source suite for multiphysics simulation and design, AIAA J. 54 (2016) 828–846. The edge-based node scheme and the corrected-average-gradient viscous flux.
- R. Hartmann, Adjoint consistency analysis of discontinuous Galerkin discretizations, SIAM J. Numer. Anal. 45 (2007) 2671–2696。伴随一致性(附录 B)。R. Hartmann, Adjoint consistency analysis of discontinuous Galerkin discretizations, SIAM J. Numer. Anal. 45 (2007) 2671–2696. Adjoint consistency (Appendix B).
- T. E. Peterson, A note on the convergence of the discontinuous Galerkin method for a scalar hyperbolic equation, SIAM J. Numer. Anal. 28 (1991) 133–140。纯对流问题上一阶迎风格式的 h1/2 收敛阶(第 15 节)。T. E. Peterson, A note on the convergence of the discontinuous Galerkin method for a scalar hyperbolic equation, SIAM J. Numer. Anal. 28 (1991) 133–140. The rate h1/2 of first-order upwinding on a purely convective problem (Section 15).
附录 B:伴随一致性
Appendix B: adjoint consistency
本页的来流处理是伴随一致的;原来的版本只在来流边界上与本页不同。本附录说明两者差在哪里、为什么这一点差别决定离散伴随在来流附近趋于什么,并在同一组网格上比较两者。
This page's inflow treatment is adjoint-consistent; the original version differs from it on the inflow boundary only. This appendix explains the difference, why it decides what the discrete adjoint approaches near the inflow, and compares the two on the same meshes.
B.1 什么是伴随一致
B.1 What adjoint consistency means
两种版本的离散伴随 ψ 都满足 ATψ = −g,都是各自离散问题的精确导数(第 8–14 节的检验对两者都成立)。伴随一致性(也叫对偶一致性)问的是另一件事:把 ATψ = −g 本身看作一个离散格式,它是不是连续伴随方程连同边界条件的相容离散。若是,加密时 ψ 逐点趋于连续伴随 λ(换算到守恒方程的乘子,附录 A.2),边界附近也一样;若不是,ψ 在区域内部仍可以趋于 λ,在边界附近却趋于另一个问题的解。两种版本的区域内部格式、壁面与出口完全相同,连续问题也相同(附录 A.1),所以差别只可能来自来流边界。
The discrete adjoints ψ of both versions satisfy ATψ = −g and are the exact derivatives of their discrete problems (the checks of Sections 8–14 hold for both). Adjoint consistency (also called dual consistency) asks something else: read ATψ = −g itself as a discrete scheme; is it a consistent discretisation of the continuous adjoint equations together with their boundary conditions? If it is, ψ approaches the continuous adjoint λ (mapped to the multipliers of the conservative equations, Appendix A.2) point by point under refinement, next to the boundary as well; if it is not, ψ can still approach λ inside the domain, but next to the boundary it approaches the solution of a different problem. The two versions share the interior scheme, the wall and the outlet, and the continuous problem (Appendix A.1), so any difference comes from the inflow boundary.
B.2 离散伴随的边界条件从哪里来
B.2 Where the discrete adjoint's boundary conditions come from
离散伴随的边界条件不是另外写的:AT 是原始格式的转置,边界上的做法经转置自动变成伴随的边界条件。有两条规则:
The discrete adjoint's boundary conditions are not written separately: AT is the transpose of the primal scheme, and what the scheme does on the boundary turns into the adjoint's boundary conditions by that transpose. Two rules:
- 被替换的行。替换后的一行 Ri,k = Ui,k −(给定值) 只依赖节点自己的 Ui,k(一致版本的来流行还依赖 Ui,ρ)。它的乘子 ψi,k 只出现在自己那一列的伴随方程里(一致版本的来流行还以 −W∞,kψi,k 出现在 ρ 那一列),是一个反作用;其余伴随方程看被替换之前的那一行,就像它的乘子是 0。所以替换一行,等于给其余的离散伴随加上“这个分量在这个节点为零”。壁面节点的动量行是一个例外:它们也被替换了,但第 7 节的阻力取的正是它们被替换之前的值,CD = −eD·Σ Ri动量/q∞。在 Lagrange 函数里,这两行因此带着乘子 −eD/q∞ 而不是 0;其余伴随方程看到的是 β = −eD/q∞,正是 A.3 表中壁面的条件(照搬“为零”就会得到 β = 0,那是错的)。数值上:把 ψ 在壁面节点的动量分量换成 −eD/q∞、ν̃ 分量换成 0 以后,替换之前各遍的转置在所有未被替换行触及的列上都为零(相对 g 的最大分量 8.1×10−15);离壁面最近一排节点的 ψρu 平均值逐级 −13.4、
−24.0、 Replaced rows. A replaced row Ri,k = Ui,k − (given value) depends on the node's own Ui,k only (the consistent version's inflow rows on Ui,ρ as well). Its multiplier ψi,k appears in its own column's adjoint equation only (the consistent version's inflow rows also, as −W∞,kψi,k, in the node's ρ column) and is a reaction; every other adjoint equation sees the row as it was before the replacement as if its multiplier were 0. So replacing a row imposes on the rest of the discrete adjoint “this component is zero at this node”. The wall nodes' momentum rows are the exception: they are replaced too, but the drag of Section 7 takes exactly their values before the replacement, CD = −eD·Σ Rimomentum/q∞. In the Lagrangian these two rows therefore carry the multiplier −eD/q∞, not 0, and every other adjoint equation sees β = −eD/q∞: exactly the wall condition of A.3's table (taking “zero” literally would give β = 0, which is wrong). Numerically: with ψ's momentum components on the wall nodes replaced by −eD/q∞ and its ν̃ component by 0, the transpose of the passes before the replacement vanishes in every column that no replaced row reaches (at most 8.1×10−15 of g's largest entry); the mean ψρu of the first row of nodes off the wall is −13.4, −24.0, −29.7 on levels 2, 3, 4, approaching −cos α/q∞ = −35.6.−29.7(第 2、3、4 级),趋向 −cos α/q∞ = −35.6。 - 边界通量依赖的状态分量。边界半面的通量 Fbc 读哪些状态分量,AT 在这些分量的列上就多出 (∂Fbc/∂U)Tψ。连续问题在来流上的通量只经温度 T 和牵引力、SA 扩散通量这些自由的量依赖解:ρ、u、ν̃ 是给定值。离散通量若还依赖节点的 ρ、u 或 ν̃,转置后就多出连续伴随没有的边界项。The state components a boundary flux reads. Whatever state components the boundary half-face's flux Fbc reads, AT receives (∂Fbc/∂U)Tψ in those columns. The continuous inflow flux depends on the solution only through the temperature T and the free quantities traction and SA diffusive flux: ρ, u and ν̃ are given. If the discrete flux also reads the node's ρ, u or ν̃, its transpose carries boundary terms the continuous adjoint does not have.
连续伴随在来流上要满足的是附录 A.3 的三条,λρ 不需要条件:伴随沿 −u 输运,来流边界是 λρ 离开区域的地方。换算到守恒方程的乘子(A.2):ψρ ↔ λρ − ν̃φ/ρ,ψρu ↔ β,ψρE ↔ ζ,ψρν̃ ↔ φ/ρ。
What the continuous adjoint has to satisfy on the inflow are the three conditions of Appendix A.3, and λρ takes none: the adjoint is transported along −u, and the inflow is where λρ leaves the domain. In the multipliers of the conservative equations (A.2): ψρ ↔ λρ − ν̃φ/ρ, ψρu ↔ β, ψρE ↔ ζ, ψρν̃ ↔ φ/ρ.
B.3 原来的来流处理为什么伴随不一致
B.3 Why the original inflow treatment is adjoint-inconsistent
格点格式原来把来流节点的 ρ、ρu、ρv、ρν̃ 四行替换成 U − U∞,能量行保留。按规则 1,其余伴随方程在来流节点上看到 ψρ = ψρu = ψρv = ψρν̃ = 0,也就是说离散伴随在来流上满足
The node scheme originally replaced an inflow node's ρ, ρu, ρv and ρν̃ rows by U − U∞ and kept its energy row. By rule 1 every other adjoint equation sees ψρ = ψρu = ψρv = ψρν̃ = 0 at an inflow node: on the inflow the discrete adjoint satisfies
- φ = 0 与连续条件相同。φ = 0 agrees with the continuous condition.
- β = 0 与 β = −ζu 不同,而 ζ 在来流上并不为零(第 4 级网格上 180° 顶点处 λ 的 ζ = −35.2)。能量行虽然保留,它在来流半面上的功 u·τn 用的是节点自己梯度给出的牵引力,不是动量行的反作用,所以 A.3 里组成 β + ζu 的两项在离散里凑不到一起。β = 0 differs from β = −ζu, and ζ is not zero on the inflow (λ's ζ = −35.2 at the 180° vertex on level 4). The energy row is kept, but the work u·τn on its inflow half-faces uses the traction of the node's own gradients, not the momentum rows' reaction, so the two terms that form β + ζu in A.3 never meet in the discrete equations.
- λρ = 0 是连续伴随没有的条件:λρ 在伴随的出口被钉住。这正是原始问题在出口多给一个条件的伴随版。结果是来流附近根本没有 A.3 的那一层:第 4 级 180° 网格线上离来流 0.055 的节点,ψρ = 12.3,λ 的对应值是 85.0(B.5 的剖面图)。λρ = 0 is a condition the continuous adjoint does not have: λρ is pinned at the adjoint's outlet. This is the adjoint version of giving the primal problem one condition too many at an outlet. The result is that the layer of A.3 is missing next to the inflow altogether: on level 4, at the node 0.055 from the inflow on the 180° mesh line, ψρ = 12.3 where λ gives 85.0 (the profiles of B.5).
B.4 伴随一致的来流处理
B.4 The adjoint-consistent inflow treatment
一致的版本改三处。质量行保留:ρ 只经来流半面上给定的质量通量 ρ∞u∞·n 进入,这一项不依赖任何状态,λρ 不受约束。ρu、ρv、ρν̃ 三行替换成 Uk − UρW∞,k(以节点自己的 ρ 给定 u、ν̃),ψρν̃ 的行被替换,φ = 0 照旧。能量行在替换之前减去 u∞ 乘两行动量行。来流半面只带对流通量,所以替换前动量行的值 ℳi 正是经来流半面作用在节点上的粘性牵引力 Fi(反作用);这一步就是把下面的混合形式里的 Fi 消去:
The consistent version changes three things. The mass row stays: ρ enters only through the given mass flux ρ∞u∞·n on the inflow half-faces, which depends on no state, so λρ is left free. The ρu, ρv and ρν̃ rows become Uk − UρW∞,k (u and ν̃ given at the node's own ρ); ψρν̃'s row is replaced, so φ = 0 as before. And the energy row subtracts u∞ times the two momentum rows before they are replaced. The inflow half-faces carry convection only, so the momentum rows' values ℳi at that point are exactly the viscous traction Fi on the node through them (the reaction); the step eliminates Fi from the mixed form
ℳi、ℰi 是不含来流半面粘性项的动量与能量平衡。把 Fi 当作未知量,它那一列的伴随方程是 ψM + u∞ψE = 0:这就是离散的 β + ζu = 0。能量平衡里来流半面没有热流,半面对流通量里压力 ρ∞Tin 与 ρ∞cpTiun 经这个组合合成 ρ∞cvunTi,转置后给出 Robin 条件里的 ρcvunζ。代码上只多两步:第 4 遍先做能量行的组合,再替换三行(第 5、9 节的演示逐句执行它们)。
ℳi and ℰi are the momentum and energy balances without the inflow half-faces' viscous terms. With Fi as an unknown, its column's adjoint equation is ψM + u∞ψE = 0: the discrete β + ζu = 0. The energy balance has no heat flux through the inflow half-faces, and in their convective flux the pressure ρ∞Tin and ρ∞cpTiun combine through this step into ρ∞cvunTi, whose transpose is the ρcvunζ of the Robin condition. In the code this is two extra steps: pass 4 combines the energy row first and then replaces the three rows (the demos of Sections 5 and 9 execute them statement by statement).
图 B.1 把附录 B 的转置规则落到本页的一个来流半面上:对流通量对节点状态 Wi = (ρ, u, v, T, ν̃) 的 Jacobian 有哪些非零列,转置后的边界项就落在哪些方向。原来的处理有 5 列非零(ρ、u、v、T、ν̃),伴随一致的处理只有 1 列(T)。格点页原来的处理还替换了来流节点的 ρ、ρu、ρv、ρν̃ 四行:第 4 遍之后只剩能量行用到半面通量,ρ、u、v 列属于被替换的分量,它们的伴随方程只给反作用,原处理的不一致来自被替换的行(附录 B 的规则 1、B.3)。粘性部分两种处理也不同:原处理的来流半面减去节点梯度给出的粘性通量(能量行里有功 u·τn),一致的处理没有粘性项(B.4);图里不画。
Figure B.1 applies Appendix B's transpose rule to one inflow half-face of this page: the non-zero columns of the convective flux's Jacobian with respect to the node state Wi = (ρ, u, v, T, ν̃) are the directions in which the transposed boundary terms land. The original treatment has 5 non-zero columns (ρ, u, v, T, ν̃), the adjoint-consistent one 1 (T). On the node page the original treatment also replaces the inflow node's ρ, ρu, ρv and ρν̃ rows: after pass 4 only the energy row uses the half-face's flux, and the ρ, u, v columns belong to replaced components, whose adjoint equations give reactions only, so the original's inconsistency comes from the replaced rows (rule 1 of Appendix B, B.3). The viscous part differs too: the original half-face subtracts the viscous flux of the node's gradients (the work u·τn in its energy row), the consistent one has none (B.4); it is not in the figure.
B.5 数值比较
B.5 The numbers
两种版本各自的连续伴随(系数取同一版本格点格式的解)与离散伴随逐级比较。下表是离来流边界 0.3 以内的节点(边界上的节点不计)上 ψ − λ 的相对均方根;离来流 0.8 以外两种版本相差无几(第 4 级:ψρ 13% 与 13%,ψρE 6% 与 6%)。
The two versions' discrete adjoints against their continuous adjoints (with the same version's node solution as coefficients), level by level. The table gives the relative RMS of ψ − λ over the nodes within 0.3 of the inflow boundary (the boundary nodes themselves left out); beyond 0.8 from it the two versions are alike (level 4: ψρ 13% and 13%, ψρE 6% and 6%).
| 级 | level | 原处理 ψρ | original ψρ | 原处理 ψρE | original ψρE | 一致 ψρ | consistent ψρ | 一致 ψρE | consistent ψρE |
|---|---|---|---|---|---|---|---|---|---|
| 2 | 96% | 69% | 82% | 56% | |||||
| 3 | 93% | 59% | 48% | 29% | |||||
| 4 | 86% | 53% | 23% | 14% |
一致的版本每加密一级,来流附近的误差约减半(第 3→4 级之比 ψρ 0.48、ψρE 0.47,一阶);原来的版本几乎不动(0.93、0.89):ψρ 96%→93%→86%,它趋于的是另一个问题的解。下图沿 180° 网格线看同一件事:一致版本的 ψ 跟着连续伴随在来流附近的那一层走,原来的版本没有这一层。
The consistent version roughly halves its error next to the inflow with each level (from level 3 to 4 the ratios are 0.48 for ψρ and 0.47 for ψρE: first order); the original barely moves (0.93 and 0.89): ψρ 96%→93%→86%, approaching the solution of a different problem. The figure below shows the same along the 180° mesh line: the consistent ψ follows the layer of the continuous adjoint next to the inflow, while the original has no such layer.
导数本身在两种版本里都是精确的。第 4 级网格上两种版本的 CD、格点离散伴随给出的导数,以及同一版本连续伴随与它的相对差(除以离散值,与附录 A 相同):
The derivatives themselves are exact in both versions. On level 4, the two versions' CD, the derivatives from the node discrete adjoint, and the same version's continuous adjoint's relative difference from them (over the discrete value, as in Appendix A):
| CD | dCD/dα | 与连续伴随之差 | vs continuous | dCD/dM | 与连续伴随之差 | vs continuous | dCD/dμref | 与连续伴随之差 | vs continuous | |
|---|---|---|---|---|---|---|---|---|---|---|
| 原处理original | 6.4399 | −1.3895 | 2.6% | −12.7630 | 7.3% | 218.3 | 1.2% | |||
| 一致(本页)consistent (this page) | 6.4560 | −1.4049 | 0.8% | −12.6740 | 4.4% | 219.0 | 0.6% |
伴随一致性管的是 ψ 在边界附近趋于什么,不直接决定导数误差的大小:导数误差还来自原始解本身、交界点与角点的奇性(附录 A.6)。格点格式上一致的版本离连续伴随的导数更近。
Adjoint consistency governs what ψ approaches next to the boundary; it does not by itself set the size of the derivative's error, which also comes from the primal solution and from the singular points at the junctions and the corners (Appendix A.6). On the node scheme the consistent version's derivatives are closer to the continuous adjoint's.
B.6 两个侧面:来流几乎与边界平行
B.6 The two side faces: inflow almost along the boundary
远场八边形上的四个来流面并不一样:正面(135°–225°)|u∞·n| = 0.210–0.226,两个侧面(90°–135°、225°–270°)只有 0.071–0.109。侧面上两种版本的原始解不同。原处理把来流节点的 ρ 直接取为 ρ∞ = 1;一致的版本只给质量通量,侧面上边界节点的 ρ 最低 0.988、0.974、0.968、0.967(第 1、2、3、4 级),正面上都在 1 的 0.3% 以内。在 96° 处沿法向进入区域 0.36:原处理 ρ 从 1 降到 0.970、T 从 1.027 升到 1.056;一致的版本 ρ 在 0.962–0.969 之间,T 几乎不变。两者从第 3 级到第 4 级都不再变化。
The four inflow faces of the far octagon are not alike: on the front (135°–225°) |u∞·n| = 0.210–0.226, on the two side faces (90°–135° and 225°–270°) only 0.071–0.109. On the side faces the two versions' primal solutions differ. The original sets the inflow nodes' ρ to ρ∞ = 1 directly; the consistent version gives the mass flux only, and on the side faces its boundary nodes' ρ drops to 0.988, 0.974, 0.968, 0.967 (levels 1, 2, 3, 4), while on the front all stay within 0.3% of 1. Going 0.36 into the domain along the normal at 96°: the original's ρ falls from 1 to 0.970 while T rises from 1.027 to 1.056; the consistent version's ρ stays between 0.962 and 0.969 with T nearly constant. Neither changes any more from level 3 to level 4.
原因在连续问题里:把定常 Navier–Stokes 方程沿来流边界的法向线性化,亚声速来流上恰有一个离开边界衰减的粘性模态,厚度约 4μe|un|/(3p):本页的数值是侧面 0.0022–0.0034、正面 0.0066–0.0071。在这一层里 ρ 变化而 ρun 与 T 几乎不变;本页任何一级网格都分辨不了它(最细的网格第 4 级,贴来流边界的第一排节点离边界 0.045)。于是层外的解看到的边界条件取决于离散怎样跨过这一层:原处理把 ρ = ρ∞ 放在边界节点上,一致的版本只给跨层不变的质量通量。同一个线性化的另一个模态朝区域内增长,厚度 0.15–0.47:它就是连续伴随在来流边界上的那一层(A.3)。附录 A 的连续伴随按光滑解推导,没有这一薄层;两种版本都在同一组网格上与它比较,结论只针对这些网格上的解与伴随。
The cause is in the continuous problem: linearise the steady Navier–Stokes equations along the normal of the inflow boundary, and a subsonic inflow has exactly one viscous mode that decays away from the boundary, of thickness about 4μe|un|/(3p): here 0.0022–0.0034 on the side faces and 0.0066–0.0071 on the front. Across this layer ρ changes while ρun and T stay nearly constant, and no mesh of this page resolves it (on the finest mesh, level 4, the first row of nodes lies 0.045 from the inflow boundary). So what boundary condition the solution outside the layer sees depends on how the discretisation steps across it: the original puts ρ = ρ∞ on the boundary node, the consistent version gives only the mass flux, which does not change across the layer. The same linearisation's other mode grows into the domain, with thickness 0.15–0.47: it is the continuous adjoint's layer at the inflow boundary (A.3). The continuous adjoint of Appendix A is derived for a smooth solution and has no thin layer; both versions are compared with it on the same meshes, and the conclusions are about the solutions and adjoints on these meshes.
参考:R. Hartmann, Adjoint consistency analysis of discontinuous Galerkin discretizations, SIAM J. Numer. Anal. 45 (2007) 2671–2696。伴随一致性是 h → 0 的性质;两种版本在每一级网格上都给出离散问题的精确导数,本页前面各节的点积、前向、复数步长与差分检验对两者都成立。
Reference: R. Hartmann, Adjoint consistency analysis of discontinuous Galerkin discretizations, SIAM J. Numer. Anal. 45 (2007) 2671–2696. Adjoint consistency is a property of the limit h → 0; on every mesh both versions give the exact derivative of their discrete problem, and the dot-product, tangent, complex-step and finite-difference checks of this page's earlier sections hold for both.