<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Younglin's CFD Blog (zh)</title>
    <description>可压缩多相流CFD研究者的工作笔记 — 公式、代码、交互式可视化</description>
    <link>https://cfdblog.cc/zh</link>
    <atom:link href="https://cfdblog.cc/feed-zh.xml" rel="self" type="application/rss+xml"/>
    <language>zh-CN</language>
    <managingEditor>noreply@cfdblog.cc (Younglin)</managingEditor>
    <lastBuildDate>Sun, 03 May 2026 20:09:47 GMT</lastBuildDate>
    <ttl>1440</ttl>
    <item>
      <title><![CDATA[隐式扩散与托马斯算法 — 用一次三对角求解换来无条件稳定]]></title>
      <description><![CDATA[越过显式爆破的墙后，稳定性的代价只是一次 O(N) 扫描

[3 min read · 1,558 words]]]></description>
      <content:encoded><![CDATA[import { HeatDiffusionExplicitVsImplicit1D } from '@/components/post-viz/2026-05-04-implicit-diffusion-thomas-algorithm/HeatDiffusionExplicitVsImplicit1D'

我曾经在晚上11点提交了一次模拟，第二天早上回到办公室打开结果文件，满屏都是NaN。那天我刚把网格细化了一倍，却忘了把时间步长缩小。漏掉CFL(Courant–Friedrichs–Lewy)条件的代价，是集群一小时的费用。

显式扩散方程有一个残酷的标度律：网格间距减半，时间步长就得减为原来的四分之一。求解1024个点的问题时，仅仅为了不爆破，就要算上几十万个时间步。这篇文章讨论的是一行就能跳出这个陷阱的隐式方法(implicit method)，以及让它在一维几乎不需要额外成本的算法 — 托马斯三对角求解器(Thomas algorithm)。最后你可以亲自把dt推大，看着显式方法发散而隐式方法保持平静。

CFL 锁住了细网格

扩散方程如下：

[equation]

其中 [math] 是浓度(或温度)，[math] 是扩散系数。最简单的显式格式(forward Euler + 中心差分)写成

[equation]

要稳定就需要 [math]。一行的 von Neumann 分析：最短波长(波长 [math])的放大因子为 [math]，要让它 [math] 就强制 [math]。

问题在于这个条件被 [math] 的 平方 锁住。把网格从 [math]，[math] 就要砍到原来的四分之一。这是数量级的暴政。

把未来值搬到右边 — 隐式的简单把戏

解决办法简单到几乎让人难为情。把右边的 [math] 改成 [math]：

[equation]

未来值在右边，就不能再一格一格地往前算了。所有单元同时耦合，变成矩阵方程：

[equation]

但回报很大。同样的 von Neumann 分析告诉我们放大因子是 [math]，对任意正 [math] 都小于 1。也就是说，无论把 [math] 推到多大都不会发散 — 这就是无条件稳定(unconditionally stable)。

代价是精度。极端大的 [math] 虽然稳定，但已经不准确了。即便如此，"不会爆破"这个保证，对跑代码的人来说就是一份心理健康。

三对角矩阵与托马斯的一次扫描

写出矩阵 [math]。一维情况下单元 [math] 只与 [math] 和 [math] 耦合，所以

[equation]

这是 三对角(tridiagonal) 矩阵 — 只有三条对角线非零。一般的高斯消元是 [math]，但对三对角而言会缩减到 [math]。这个算法被称为托马斯算法 — 1949年 Llewellyn Thomas 在 IBM 内部备忘录里整理了它。

托马斯算法的核心是两步。

1. 前向消元 — 从上往下扫，一边消去次对角，一边算出新的对角 [math] 与右端 [math]。
2. 后向回代 — 从最后一行倒着代入。

每一步每个单元只用4到5次浮点运算，存储也只需要三个数组。完整矩阵根本不必驻留内存。

用 NumPy 比较显式与隐式

[code block]

在 [math] 时显式方法60步就被推到了 [math]。同样的时间步长下，隐式方法只是平稳地扩散开。

自己把 dt 推大试试

下面的模拟可以亲自操作。用滑块把 [math…

---
Read more: https://cfdblog.cc/zh/posts/2026-05-04-implicit-diffusion-thomas-algorithm]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/2026-05-04-implicit-diffusion-thomas-algorithm</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/2026-05-04-implicit-diffusion-thomas-algorithm</guid>
      <pubDate>Mon, 04 May 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>수치해석</category>
      <category>implicit</category>
      <category>diffusion</category>
      <category>Thomas-algorithm</category>
      <category>stability</category>
    </item>
    <item>
      <title><![CDATA[[论文阅读] 声速发散而时间步幸存 — Orlando–Bonaventura(2024) 非理想气体 AP-IMEX]]></title>
      <description><![CDATA[在低马赫与任意 EOS 下让时间步摆脱声速约束的 AP-IMEX-DG 格式综述与 NumPy 复现

[4 min read · 1,991 words]]]></description>
      <content:encoded><![CDATA[import { APIMEXAcousticPulse1D } from '@/components/post-viz/2026-05-03-orlando-bonaventura-ap-imex-nonideal-gas/APIMEXAcousticPulse1D'

大气模型工作在马赫 0.001,宇宙爆炸模拟工作在马赫 100。用同一个求解器同时拿下两端的愿望已经持续了半个世纪。Orlando 和 Bonaventura 的 2024 年论文(arXiv:2402.09252v4)把这一愿望推进到非理想气体领域。核心思路只有两条:在时间离散中仅对压力项做隐式处理,时间步就能从声速中解放出来;而这一解放在 SG-EOS 与一般三次状态方程(Van der Waals、Peng–Robinson)下同样成立。

30 秒概览

- 作者: Giuseppe Orlando, Luca Bonaventura
- 单位: École polytechnique / Politecnico di Milano
- arXiv: 2402.09252v4(v4,2025-10-22)
- 目标: 在所有马赫数与任意 EOS 下实现渐近保持(AP)的时间积分
- 空间离散: 间断 Galerkin 方法
- 验证算例: 等熵涡、Gresho 涡、RT 不稳定性、跨声速冲击 — 扩展到 SG-EOS 和三次 EOS

显式格式在两处崩溃

显式时间积分会在两个时间尺度相撞的地方崩溃两次。

第一处是声速。压缩 Euler 系统中信号以 [math] 传播,当 [math] 变小时,[math] 完全压制 [math]。显式 CFL 受限于 [math],[math] 时时间步直接缩小一百倍。大气与海洋模拟经常掉进这个陷阱。

第二处是 EOS 的非线性。理想气体里 [math] 就到此为止;三次 EOS 中 [math] 是 [math] 的非线性函数。显式格式一旦把声速估错,网格单元会跌入负压区,EOS 自身也就失去定义。

本论文把两个问题打包看待。把显式声学项搬到隐式一侧,第一个陷阱解除;再把这个隐式步骤写成与 EOS 无关的形式,第二个陷阱也随之消失。

渐近保持到底意味着什么

AP(asymptotic-preserving)用一句话讲:连续模型 [math] 在 [math] 时收敛到极限模型 [math],那么离散化 [math] 也必须在同一极限下相容地收敛到 [math]。同时稳定性条件不依赖 [math]。

这里 [math] 是 [math],[math] 是不可压缩 Euler 方程。用熟悉的展开写出来:

[equation]

[math] 是零阶(不可压缩极限),[math] 是一阶修正,[math] 是二阶修正。AP 格式的离散解保留同样的层级。

数值含义很清楚。[math] 时测得的压力扰动应当是 [math] 量级。显式 Roe 格式做不到这一点,无论网格多细都会产生 [math] 的噪声(Guillard–Viozat,1999)。AP-IMEX 完整保留这一缩放。

仅压力隐式 — IMEX 拆分

关键技巧来自 Cordier–Degond–Kumbaro(2012)的拆分:动量方程里只把 [math] 推到隐式一侧,其余仍然显式。

[equation]

[equation]

[equation]

[math] 是密度,[math] 是速度,[math] 是压力,[math] 是单位质量总能,[m…

---
Read more: https://cfdblog.cc/zh/posts/2026-05-03-orlando-bonaventura-ap-imex-nonideal-gas]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/2026-05-03-orlando-bonaventura-ap-imex-nonideal-gas</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/2026-05-03-orlando-bonaventura-ap-imex-nonideal-gas</guid>
      <pubDate>Sun, 03 May 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>논문리뷰</category>
      <category>asymptotic-preserving</category>
      <category>IMEX</category>
      <category>low-mach</category>
      <category>Discontinuous-Galerkin</category>
      <category>non-ideal-gas</category>
    </item>
    <item>
      <title><![CDATA[[论文综述] 选择跳跃更小的那一个 — Deng (2018) MUSCL-THINC-BVD 界面重构]]></title>
      <description><![CDATA[比较两个候选重构函数在单元边界上的变差，挑选更小者的BVD原理

[4 min read · 1,940 words]]]></description>
      <content:encoded><![CDATA[import { MUSCLTHINCBVDPicker } from '@/components/post-viz/2026-05-02-muscl-thinc-bvd-interface-reconstruction/MUSCLTHINCBVDPicker'

东京工业大学 Xiao 课题组在 2018 年做了一项很少有人喜欢公开的测量。他们对可压缩两相流模拟跑了 1000 步，再去测界面厚度——原本只有一个网格的跳跃，已经扩散到了八个网格。即便换用 WENO，结果也差不多。每步看似耗散很小的格式，长时间累计后仍会把界面磨平。本文整理他们对这个问题的回答 —— MUSCL-THINC-BVD 重构。思路很朴素：对每个网格同时构造两个候选，选择在网格边界上跳跃更小的那一个。

一页摘要

- 作者 / 期刊: Deng, Inaba, Xie, Shyue, Xiao. Journal of Computational Physics 371 (2018) 945–966.
- 目标问题: 用五方程模型(five-equation model)模拟可压缩两相流时，物质界面随时间逐渐被磨平。
- 方案: 在每个网格同时构造 MUSCL(光滑区适用)和 THINC(跳跃区适用)两个候选重构函数，比较它们在网格边界上的跳跃和，取较小者，即 BVD (Boundary Variation Diminishing) 算法。
- 新意所在: 不需要后处理 anti-diffusion 或人工压缩。同一条 BVD 规则适用于体积分数和其他守恒量，变量间一致性自动得到保证。

两个相互冲突的需求

可压缩两相流的数值方法同时面临两项要求：光滑区要精度高、耗散低；跳跃区(界面、激波)要单调、且厚度保持薄。让一个函数同时把两件事都做好并不容易。

MUSCL 是分段线性重构，保单调但导数只有一阶精度。每次穿越界面都会刮掉一点，长时间累计就让跳跃变胖。反之，THINC 在每个网格内拟合一个 tanh 跳跃，能把界面压缩到一两格内，但用在光滑区会制造假的台阶。

论文的出发点是一个决定：不要把两者糅合成一个函数，而是在每个网格里挑一个。

MUSCL — 可靠的扩散器

基线候选是带 minmod 斜率限制器的 MUSCL。

[equation]

其中 [math] 为网格平均，[math] 为网格中心斜率，minmod 在两差分同号时返回绝对值较小者，异号时返回零。

候选的边界值：

[equation]

在任何位置都安全可用，没有振荡，但跳跃厚度会缓慢扩张。

THINC — 模仿跳跃的单调函数

THINC (Tangent of Hyperbola for INterface Capturing) 在每格内用双曲正切拟合跳跃。

[equation]

[math] 为从邻格平均取出的最小值与振幅，[math] 表示跳跃方向，[math] 控制跳跃厚度，[math] 是为保持网格平均而求解的跳跃中心。

[math] 在 1.4–2.0 之间稳定，1.6 是标准值。[math] 越大跳跃越压缩到单格内，看起来很漂亮，但若被错误地用到光滑区，就会产生锯齿状假跳跃。

BVD — 在两个候选之间度量变差

核心思想出现了。既然有两个候选，就可以问：在与邻格重构相遇的边界上，哪一个产生的跳跃更小。第 [math] 格的 总边界变差 (Total Boundary Variation, TBV) 定义为

[equation]

其中 [math] 为候选(M…

---
Read more: https://cfdblog.cc/zh/posts/2026-05-02-muscl-thinc-bvd-interface-reconstruction]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/2026-05-02-muscl-thinc-bvd-interface-reconstruction</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/2026-05-02-muscl-thinc-bvd-interface-reconstruction</guid>
      <pubDate>Sat, 02 May 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>논문리뷰</category>
      <category>compressible-multiphase</category>
      <category>MUSCL</category>
      <category>THINC</category>
      <category>BVD</category>
      <category>interface-capturing</category>
    </item>
    <item>
      <title><![CDATA[特征线相撞之处,激波诞生 — Burgers 方程与 (x,t) 平面]]></title>
      <description><![CDATA[非线性自对流如何把光滑曲线撕成激波

[4 min read · 1,826 words]]]></description>
      <content:encoded><![CDATA[import { BurgersShockBirth } from '@/components/post-viz/2026-05-01-burgers-characteristics-shock-formation/BurgersShockBirth'

1948 年,荷兰物理学家 J. M. Burgers 抛出了一个一行的方程作为湍流模型。一条光滑曲线在没有外力的情况下,有限时间内被撕成一道垂直悬崖 — 这是非线性双曲型 PDE 中最短的戏剧。本文用特征线(characteristic,信息在时空中流动的曲线)的几何手算激波形成的时刻,梳理弱解(weak solution,在可微性失效处由积分形式定义的解)如何用一条线截断多值区域,然后用 60 行 Python 重现同样的图像。文末你可以亲手在 (x,t) 平面上看直线相撞。

两条直线在同一个点相遇

双曲型方程的核心是信号传播。只要信息以固定速度沿特征线流动,一切都很平静。线性对流 [math] 中若 [math] 为常数,特征线为平行直线,初始形状只是横向滑动。这幅画里没有激波的位置。

非线性出现时一切都变了。当 [math] 依赖于 [math] 本身时,大值跑得快,小值跑得慢。快的部分追上慢的部分的瞬间,(x,t) 平面同一个点同时收到两个值。函数变成多值(multi-valued)— 物理上不可能 — 那一刻就是激波的诞生。

自我搬运的方程

Burgers 方程的守恒形为:

[equation]

[math] 是守恒标量,[math] 是通量。链式法则展开得到非守恒形:

[equation]

对流速度 [math]。它把自己搬运自己。这一个非线性是一切戏剧的源头。雅可比 [math] 为正处信号向右,为负处向左。当初始分布在空间上变号 — 正弦曲线就是典型 — 快的位置就会去追慢的位置。

特征线绘出的 (x,t) 平面

特征线满足 [math]。沿其上随动导数 [math] 为零,所以 [math] 沿这条线被冻结在初始值。结果是,(x,t) 平面上的特征线是 斜率为 [math] 的直线。出发点 [math] 处的初值 [math] 就是这条线的速度。

对初始条件 [math]:

- 从波峰([math])出发的线急剧右倾(快)
- 从波谷([math] 时,直接解析在同一个 [math] 处吐出三个 [math] — 不可能。出路是 弱解:放弃微分形,改用积分守恒律放宽定义。

[equation]

即使 [math] 不可微 — 也就是不连续 — 这个式子仍然成立。设两个平坦状态 [math]、[math] 由速度为 [math] 的激波连接:

[equation]

这就是 Rankine–Hugoniot 条件。激波速度等于两个状态的算术平均。该条件用一条线切割多值区域,使两边切下的面积相等(equal-area rule,等面积律)。

此外还需要熵条件。物理上的激波只在 [math] 时存在;若 [math]A[math]t^[math]k[math]\Delta t \le \Delta x / \max|q|[math]dt[math]dt[math]q$ 可能局部突起,这一点尤为重要。

(2) 熵处理错误. 仅满足 Rankine–Hugoniot,非物理的 expansion shock 也会成为解。Roe 这类简单的线性化求解器在跨音速 rarefaction(扇形跨过零)区域会出现"entropy glitch"。Goduno…

---
Read more: https://cfdblog.cc/zh/posts/2026-05-01-burgers-characteristics-shock-formation]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/2026-05-01-burgers-characteristics-shock-formation</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/2026-05-01-burgers-characteristics-shock-formation</guid>
      <pubDate>Fri, 01 May 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>Burgers</category>
      <category>hyperbolic</category>
      <category>shock</category>
      <category>characteristics</category>
      <category>수치해석</category>
    </item>
    <item>
      <title><![CDATA[20℃的水也会沸腾 — 空化的物理]]></title>
      <description><![CDATA[减压引发的沸腾、空化数、以及气泡溃灭的万级冲击。

[4 min read · 1,918 words]]]></description>
      <content:encoded><![CDATA[import { VenturiCavitationFlow } from '@/components/post-viz/2026-04-30-cavitation-number-vapor-pressure/VenturiCavitationFlow'

20℃的水也会沸腾。只要把压力降得足够低就行。"水的沸点是100℃"这条课本结论隐藏着一个被省略的脚注:在1个大气压下。真正决定沸腾的并不是温度,而是饱和蒸气压与周围压力之间的平衡。当水在泵叶轮入口或船用螺旋桨叶尖加速,静压随之下降,常温的水也会突然沸腾。这就是空化(cavitation, 空蚀现象)。本文整理空化为何发生、如何用一个无量纲数衡量风险,以及气泡消失瞬间为何会激起万级冲击波。文末附一段在文丘里管中预测空化区的Python代码,以及一个可以亲手操作的模拟器。

沸点不由温度决定

水的饱和蒸气压是温度的函数。

| 温度 | 饱和蒸气压 [math] |
|---|---|
| 20℃ | 2.34 kPa(≈ 17.5 mmHg) |
| 60℃ | 19.9 kPa |
| 100℃ | 101.3 kPa(≈ 760 mmHg) |
| 200℃ | 1554 kPa(≈ 15 atm) |

100℃之所以听起来特别,只因为在该温度下 [math] 恰好等于1个大气压。在压力锅里(约2个大气压)沸点升至120℃;在珠峰之巅(0.3个大气压)水在70℃就沸腾。

把这个逻辑反过来:想煮20℃的水,只需把外界压力降到约2.5 kPa,即1个大气压的1/40。一个家用真空泵就足够把温水煮沸。

麻烦的是,流动的水根本不需要真空泵。

流动制造的低压 — Bernoulli的阴影

在无粘定常流中,沿一条流线伯努利方程成立。

[equation]

[math] 是静压,[math] 是密度,[math] 是速度,[math] 是高度。在同一高度上,速度变快的位置静压必然下降。文丘里喉部、翼型负压面、泵叶轮入口 — 凡是流速被加快的地方,压力都会同时跳水。

如果继续推到极端,静压一旦低于工作温度对应的 [math],液体就再也维持不住。微小气体核作种子,蒸气泡爆发式生长。这就是空化的诞生瞬间。

一句话总结:空化不是被加热出来的沸腾,而是由流体力学减压触发的沸腾。

空化数 σ — 用一个数衡量风险

设计者把"这台泵会不会空化"压缩成一个无量纲数,空化数。

[equation]

[math] 是参考点的静压,[math] 是参考速度,[math] 是工作温度下的饱和蒸气压。分子代表"蒸气压之上还剩多少压力余量",分母代表"流动能贡献的最大动压"。

[math] 越大越安全。即便流动充分加速,动压全部转化也不足以把静压拉到 [math] 之下。一旦 [math] 跌到临界值 [math] 以下,空化就开始(initiation)。每种翼型或叶轮的 [math] 不同,通常通过风洞或水洞实验测定。

旋转机械工程中,NPSH(净正吸入扬程) 起到同等作用。NPSH不足意味 [math] 偏小,泵就在沸腾。

气泡之死 — 万级冲击波

如果空化只是产生气泡,问题倒不大。真正的破坏来自气泡的消亡。

气泡漂过低压区,被流动带入压力恢复的区域。在那里,气泡内的蒸气被周围液体猛然挤压。球形气泡半径 [math] 的演化由 Rayleigh–Plesset 方程刻画。

[equation]

[math] 是气泡内压,[math] 是表面张力,[math] 是运动粘度。当外压远高…

---
Read more: https://cfdblog.cc/zh/posts/2026-04-30-cavitation-number-vapor-pressure]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/2026-04-30-cavitation-number-vapor-pressure</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/2026-04-30-cavitation-number-vapor-pressure</guid>
      <pubDate>Thu, 30 Apr 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>유체역학</category>
      <category>Cavitation</category>
      <category>Multiphase</category>
      <category>Bernoulli</category>
      <category>유동현상</category>
    </item>
    <item>
      <title><![CDATA[SPH 粒子法求解流体 — 从核函数到人工粘性]]></title>
      <description><![CDATA[无网格粒子法 SPH 的原理、代码与陷阱

[4 min read · 1,895 words]]]></description>
      <content:encoded><![CDATA[import { SPHParticleDrop2D } from '@/components/post-viz/2026-04-29-sph-meshfree-particle-hydrodynamics/SPHParticleDrop2D'
import { SPHKernelShapeExplorer } from '@/components/post-viz/2026-04-29-sph-meshfree-particle-hydrodynamics/SPHKernelShapeExplorer'

1992 年,Joe Monaghan 在一篇天体物理综述中抛出了一个挑衅性的设想:别再围绕恒星铺网格了。把气体撒成数千个相互重叠的粒子,让它们通过光滑的压力场相互作用。三十年后,Smoothed Particle Hydrodynamics(SPH)在天体物理、自由表面流和冲击模拟中占据了一席之地。本文追踪让 SPH 立得住的四个方程,以及人们经常踩进去的坑,并让你在浏览器里直接拨动粒子。

没有网格的流体 — SPH 的起点

欧拉法把坐标系钉死,看流动从上面流过。SPH 反过来,把坐标系绑在流场上,让每个粒子带着自己的速度和密度一起走。拉格朗日形式的连续方程和动量方程是:

[equation]

其中 [math] 为密度,[math] 为速度,[math] 为压力,[math] 为重力。沿粒子轨迹看,左边的时间导数就是普通的 [math]。问题在右边的空间导数。粒子集合没有规则的邻居,该怎么计算 [math] ?这就是 SPH 要回答的问题。

核函数 W(r, h) — 粒子构造的虚拟体积

办法是卷积。在每个粒子周围放一个钟形函数 [math],把任意场 [math] 用邻居粒子的加权和近似:

[equation]

[math] 是粒子质量,[math] 是密度,[math] 是平滑长度。比值 [math] 解释为粒子 [math] 占据的体积。求导也照搬到核函数上 — [math]。网格上的差分变成了核函数的导数。

合格的核函数要满足两条:积分为 1,[math] 时收敛到狄拉克函数。常用的形式都是紧支撑的 — 在 [math]r = 2h[math]r[math]i[math]\rho0[math]K[math]\gamma[math]K[math]c0 = \sqrt{\gamma K / \rho0}[math]\nabla P / \rho[math]j[math]i[math]i[math]j[math][math]K[math]\mu[math]hi[math]fi[math]\delta[math]h$ 同时决定了开销和精度。下次遇到自由表面或爆炸模拟时,不妨想到一万颗漂浮粒子,而不是再加一层自适应网格。

参考文献

- Monaghan, J. J. (1992). Smoothed Particle Hydrodynamics. Annual Review of Astronomy and Astrophysics, 30, 543.
- Monaghan, J. J., and Gingold, R. A. (1983). Shock simulation by the particle method SPH. Journal of Computational Physics, 52(2), 374.
- Müller, M., Charypar, D., and Gross, M. (2003).…

---
Read more: https://cfdblog.cc/zh/posts/2026-04-29-sph-meshfree-particle-hydrodynamics]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/2026-04-29-sph-meshfree-particle-hydrodynamics</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/2026-04-29-sph-meshfree-particle-hydrodynamics</guid>
      <pubDate>Wed, 29 Apr 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>SPH</category>
      <category>Meshfree</category>
      <category>Lagrangian</category>
      <category>Multiphase</category>
      <category>Astrophysics</category>
    </item>
    <item>
      <title><![CDATA[漩涡的两副面孔 — 自由涡、强迫涡与亥姆霍兹]]></title>
      <description><![CDATA[从浴缸漩涡到龙卷风，涡量到底度量了什么

[4 min read · 1,979 words]]]></description>
      <content:encoded><![CDATA[import { RankineVortexExplorer } from '@/components/post-viz/2026-04-28-rankine-vortex-helmholtz/RankineVortexExplorer'

把浴缸的塞子拔掉，水会一圈圈地转。我们把这一幕称作"水在旋转"。可流体力学家面对这片区域的大部分时，会反过来说："这里没有发生旋转（irrotational）。"看似矛盾的两句话里，藏着涡（vortex）真正的样子。本文把同一幅画里共存的两种漩涡分开：自由涡（free vortex，速度按 [math] 分布）与强迫涡（forced vortex，速度按 [math] 分布），讲清楚涡量（vorticity，流体微团自转角速度的两倍）究竟在度量什么，再追到亥姆霍兹定理为什么把涡称作"不灭"。

浴缸漩涡真的是"旋转"吗

"旋转"这一个词里塞着两层意思。其一是 公转 — 围着某个点做圆周运动。其二是 自转 — 微团自己绕自己的轴转。在浴缸漩涡里，水的微团确实公转。可是自转呢？远离排水口的那块区域几乎没有。一片漂在水面的小叶子沿着圆形轨迹走，可它自己并不转动，始终把同一面对着排水口。

在流体力学里，"旋转"指的就是自转。所以自由涡除了奇异的中心点以外，整个区域都被归为"无旋"。

强迫涡与自由涡：同一幅画，不同的灵魂

往一个旋转的容器里搅水搅久了，整桶水会像刚体一样一起转。这叫 强迫涡。每一个微团既公转也自转。

[equation]

其中 [math] 是切向速度，[math] 是刚体的角速度，[math] 是到中心的距离。速度与半径成正比。

而在忽略粘性的理想流体里自然形成的漩涡，是 自由涡（即势涡）。

[equation]

[math] 是 环量（circulation） — 沿一条闭合曲线的速度线积分。速度按 [math] 衰减，到中心发散。这一奇点在真实流体里被粘性所驯服。

| | 强迫涡 | 自由涡 |
|---|---|---|
| 速度 | [math] | [math] |
| 自转 | 有 | 无 |
| 能量输入 | 持续不断 | 仅在最初一次 |
| 日常例子 | 搅动的杯水 | 浴缸、龙卷风 |

同样的圆形流动，自转的有无却相反。把这一差异化为单一标量的，就是涡量。

涡量度量了什么

涡量 [math] 是速度场的旋度（curl）。

[equation]

二维情形里只剩 [math] 分量：

[equation]

其中 [math] 分别是 [math] 方向的速度分量。这一值正好等于 流体微团自转角速度的两倍。

代入强迫涡，[math] 是常数 — 整片区域都在自转。代入自由涡，除中心外处处 [math]。流线一样圆，自转情况却恰好相反。

兰金组合涡 — 龙卷风的蓝图

真实世界里的漩涡不会只听一种法则。靠近中心的地方粘性强，流体像刚体一样转；远处粘性可忽略，自由涡的法则接管。把两者拼起来的模型就是 兰金（Rankine）组合涡。

[equation]

[math] 是核心半径，[math] 是核心边界处的最大切向速度。两段表达式在 [math] 光滑相接。龙卷风的风速分布、飞机翼尖脱出的翼尖涡、排水口上方的吸入涡，都接近这一形状。核心内是有旋区，核心外是无旋区。

亥姆霍兹定理 — 涡的不灭

在无粘流体中，作用在微团上的力只有压力，而压力指向微团中心，无法产生力矩。所以 此前不自转的微团永远不会开始自转，正在自转的微团永远不会停下。这就是亥姆霍兹…

---
Read more: https://cfdblog.cc/zh/posts/2026-04-28-rankine-vortex-helmholtz]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/2026-04-28-rankine-vortex-helmholtz</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/2026-04-28-rankine-vortex-helmholtz</guid>
      <pubDate>Tue, 28 Apr 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>Vortex</category>
      <category>Vorticity</category>
      <category>유체역학</category>
      <category>유동현상</category>
      <category>Helmholtz</category>
    </item>
    <item>
      <title><![CDATA[四叉树 AMR — 让网格只在需要的地方生长]]></title>
      <description><![CDATA[Berger–Oliger 四十年来的自适应网格数据结构与加密判据梳理

[4 min read · 2,076 words]]]></description>
      <content:encoded><![CDATA[import { AMRQuadtreeRefinement } from '@/components/post-viz/2026-04-27-amr-quadtree-cell-refinement/AMRQuadtreeRefinement'

1984 年,斯坦福的 Marsha Berger 和 Joseph Oliger 卡在激波追踪上。他们的代码铺了一百万个网格,激波附近做有意义工作的大约只有 1%。剩下的 99% 在反复以高精度重新计算均匀的自由流。当年他们发表在 Journal of Computational Physics 的论文成了 Berger–Oliger AMR 的起点,同样的思想至今活在 OpenFOAM 的 dynamicRefineFvMesh、AMReX、Chombo、p4est 之中。本文沿着它的核心 — 四叉树数据结构 与 加密判据 — 走一遍,先用 Python 跑一段 1D 自适应网格,再在浏览器里看网格如何分裂。

均匀网格为什么浪费 90%

跑过 3D 可压 RANS 的人都熟悉这个权衡。把网格减半,单步开销下降到 1/8,但激波、剪切层、分离这些梯度大的区域分辨率也跟着崩。反过来按这些区域去加密整个网格,自由流的网格也跟着变小,内存与时间一起爆炸。

办法很简单。只在需要的地方加密。 定量上,下面这个估计就基本够用:

[equation]

其中 [math] 是最大加密级别,[math] 是需要细化的体积,[math] 是整个计算域体积。对于激波这种类一维曲面奇异点,[math],网格数量相对均匀第 [math] 级会跌到个位数百分点。

h-、p-、r- — 自适应的三条路

自适应网格(adaptive mesh,根据解的分布自身改变的网格)按改变的对象分成三类。

- h-自适应: 缩小网格尺寸 [math]。最直观也最常用,通常说 AMR 指的就是这一种。
- p-自适应: 网格尺寸不变,提高多项式阶 [math]。在 DGM、SEM(谱单元法)中常见。
- r-自适应(relocation): 网格数与阶都不变,把节点迁移到梯度大的位置。内存恒定但网格畸变较难管理。

本文聚焦最常用的 h-AMR,特别是 2D 四叉树(三维则为八叉树)。

四叉树 — 单元拥有自己孩子的数据结构

均匀网格只需一个一维数组。自适应网格需要 树。一个单元加密时生出 4 个子单元,每个子单元指向其父。子单元再加密就有了孙子。

[code block]

split 中用父值初始化每个子单元是为了 守恒。父单元的积分量 [math] 必须等于四个子单元之和。简单复制是一阶插值,生产代码通常配合父单元的斜率(MUSCL 型)做二阶精度的 prolongation。

切在哪里 — 加密判据

四叉树本身只是空容器。真正关键的是 切哪个单元,即加密判据。生产中常见的五种:

| 判据 | 形式 | 抓住什么 |
|---|---|---|
| 一阶导数 | [math] | 激波、剪切层 |
| 二阶导数 | [math] | 大曲率区域 |
| Hessian Frobenius | [math] | 各向异性检测 |
| Richardson 估计 | [math] | 真实离散误差 |
| 物理阈值 | [math] | 涡核 |

OpenFOAM 的 dynamicRefineFvMesh 对用户定义场设阈值,AMReX 把每单元布尔函数 tagcells() 留给用户填。标记什么决定 AMR …

---
Read more: https://cfdblog.cc/zh/posts/2026-04-27-amr-quadtree-cell-refinement]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/2026-04-27-amr-quadtree-cell-refinement</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/2026-04-27-amr-quadtree-cell-refinement</guid>
      <pubDate>Mon, 27 Apr 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>AMR</category>
      <category>쿼드트리</category>
      <category>메시</category>
      <category>알고리즘</category>
      <category>수치해석</category>
    </item>
    <item>
      <title><![CDATA[[论文评论] 在风暴来临前算完仿真 — Casulli–Walters(2000) 非结构正交网格的浅水方程]]></title>
      <description><![CDATA[在大时间步长下仍然不发散的半隐式浅水算法

[4 min read · 1,983 words]]]></description>
      <content:encoded><![CDATA[import { ShallowWaterCasulli1D } from '@/components/post-viz/2026-04-26-casulli-walters-unstructured-shallow-water/ShallowWaterCasulli1D'

汉堡的 BAW 实验室在 1990 年 6 月需要重现 Jade–Weser 河口 13 天的潮位历史。网格用了 15 万个非结构三角形,时间步长要 5 分钟,而且仿真必须比实时跑得更快,才能在排程里塞下下一个算例。显式求解器里,自由表面波速 [math] 决定 CFL 上限。28 m 深的区域 [math] m/s,最小网格边长接近 [math] m,显式步长上限就是 0.2 秒 — 13 天等于 560 万步。本文跟随 Casulli 与 Walters(2000) 提出的 非结构正交网格半隐式算法 突破这堵墙,并且实地跑一个 1D 简化版。结论先说:只把压力项做隐式处理,得到的系统恰好是 SPD,适合 PCG。

论文元信息
- 作者: Vincenzo Casulli (Univ. of Trento), Roy A. Walters (USGS)
- 期刊: International Journal for Numerical Methods in Fluids, 32, 331–348 (2000)
- 题目: "An unstructured grid, three-dimensional model based on the shallow water equations"
- 关键词: semi-implicit, shallow water, unstructured orthogonal grid, wetting/drying

显式求解器为何在河口失灵

浅水方程的自由表面波很快。深 10 m 时 [math] m/s,深 100 m 时 [math] m/s。流速 [math] 通常不到 1 m/s,所以物理时间尺度是 [math],显式步长却受制于 [math]。两者比值 [math],显式代码必须把时间切得比流动需要的细 10 到 30 倍。

非结构网格让情况更糟。河口网格里大小不一的单元混在一起,最小那一格决定全局时间步长。Big Lost River 网格在 1.2 km × 1 km 区域内有 12,622 个三角形,最小边接近 5 m,显式上限大约是 0.5 秒。

办法是「慢项显式,快项隐式」。只把自由表面压力梯度做隐式处理,波速就从稳定性条件中消失。

正交非结构网格 — Voronoi–Delaunay 的对偶

普通有限差分套到非结构网格上有两道坎。单元间距随单元形状变化,梯度近似变得不对称。曲线坐标变换又会引入新项,损害精度和稳定性。

Casulli 与 Walters 走的是绕路。正交非结构网格(orthogonal unstructured grid) — 相邻两单元中心连线与它们共享的边相互垂直。Voronoi 多边形与其对偶 Delaunay 三角剖分(在三角形全为锐角时)严格满足这个条件。

正交条件的回报很清楚。在每条边上只定义法向速度 [math],自由表面压力梯度 [math] 就化为简单差分 [math],无需曲率修正,离散保持一致。

半隐式分裂: θ 方法分离两个时间尺度

Casulli 的 θ 方法用隐式因子 [math] 参数化时间积分。动量方程把自由表面梯度取作 [math],自由表面方程…

---
Read more: https://cfdblog.cc/zh/posts/2026-04-26-casulli-walters-unstructured-shallow-water]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/2026-04-26-casulli-walters-unstructured-shallow-water</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/2026-04-26-casulli-walters-unstructured-shallow-water</guid>
      <pubDate>Sun, 26 Apr 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>논문리뷰</category>
      <category>shallow-water</category>
      <category>semi-implicit</category>
      <category>unstructured-grid</category>
    </item>
    <item>
      <title><![CDATA[[论文评述] 当WENO把小涡抹平时 — Fu(2019) TENO低耗散有限体积格式]]></title>
      <description><![CDATA[5阶WENO-JS在光滑区域也过度耗散的原因,以及TENO用锐截断修正它的方法

[3 min read · 1,729 words]]]></description>
      <content:encoded><![CDATA[import { TENOvsWENOAdvection1D } from '@/components/post-viz/2026-04-25-teno-low-dissipation-shock-capturing/TENOvsWENOAdvection1D'

在斯坦福Center for Turbulence Research,Lin Fu在运行湍流直接数值模拟时注意到一件奇怪的事。5阶WENO-JS捕捉激波没有问题,但远离激波的小涡也随时间变得模糊。格式标榜5阶精度,实际分辨率却更像3阶中心差分。本文评述Fu(2019)论文揪出原因的工作,并在相同初始条件下并排运行WENO-JS与TENO-5进行对比。先给结论:非线性权的连续性一直是隐藏成本。

论文信息与背景

- 作者: Lin Fu(Stanford Center for Turbulence Research)
- 期刊: Computer Physics Communications 235 (2019) 25–39
- DOI: 10.1016/j.cpc.2018.10.009
- 关键词: TENO, High-order schemes, Shock-capturing, Low-dissipation, Finite-volume method

WENO-JS的隐藏损耗

经典WENO-JS(Jiang–Shu, 1996)在三个小模板[math]上分别计算光滑性指标[math],再用非线性权混合多项式。

[equation]

其中[math]是恢复5阶精度的最优线性权,[math]防止除零。问题在于这些权是连续的。即便模板发生极小扰动,在本应保持[math]的光滑区域中,[math]也会微小地移动,让次数更低的模板占据权重。

结果是,光滑波动经过数十步后振幅逐渐被削去,相位误差累积。在LES(大涡模拟)这类激波与湍流涡共存的模拟中,这种耗散是致命的。

TENO的两个思路: 强尺度分离与锐截断

Fu做了两项改变。

其一,重排模板结构。在三个3点小模板[math]之外,新增一个5点大模板[math]。若[math]干净,故事就此结束 — 其他模板根本不参与。

其二,权被二值化。光滑性判定由截断参数[math]完成。

[equation]

$[math]CT = 10^{-5}[math]CT[math]10^{-3}[math]10^{-7}[math]CT[math]CT[math]CT = 10^{-5}[math]10^{-6}[math]S3[math]\beta3[math]\deltak[math]CT[math]CT[math]\beta[math]wk[math]CT[math]CT$参数就在稳定性与低耗散之间做权衡,所以必须与网格细化一起做灵敏度分析。

---
Read more: https://cfdblog.cc/zh/posts/2026-04-25-teno-low-dissipation-shock-capturing]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/2026-04-25-teno-low-dissipation-shock-capturing</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/2026-04-25-teno-low-dissipation-shock-capturing</guid>
      <pubDate>Sat, 25 Apr 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>논문리뷰</category>
      <category>TENO</category>
      <category>WENO</category>
      <category>shock-capturing</category>
      <category>high-order</category>
    </item>
    <item>
      <title><![CDATA[Lax–Wendroff 在阶跃处颤抖 — 用 Flux Limiter 构建二阶 TVD 对流格式]]></title>
      <description><![CDATA[绕开 Godunov 定理,构造单调的二阶对流格式

[3 min read · 1,575 words]]]></description>
      <content:encoded><![CDATA[import { LimiterAdvection1D } from '@/components/post-viz/2026-04-24-flux-limiter-tvd-advection/LimiterAdvection1D'

一次测试里,阶跃的前后冒出了奇怪的凸包。我在用 Lax–Wendroff 求解线性对流方程(linear advection,恒定速度场下的纯平移),初始条件是简单的矩形脉冲。按说二阶格式应该比一阶迎风更锐利,结果却是阶跃前出现下冲、后出现上冲。日志里 CFL = 0.5,稳定性条件明显满足。

问题不是算法不稳定,而是算法不单调。

振荡的来源 — Godunov 的墙

一维线性对流方程为

[equation]

若速度 [math] 恒定,解就是初始形状原样向右平移。数值上我们在单元界面上定义通量 [math],然后写

[equation]

这叫 flux-conserving form,能把质量、动量、能量等守恒量保持到机器精度。Lax–Wendroff 是在此基础上加了二阶 Taylor 修正的线性格式。

但 Godunov 在 1959 年证明的定理很残酷:对线性常系数对流而言,不存在同时保持单调性(monotonicity)且具有二阶以上精度的线性格式。 两者必须舍一。Lax–Wendroff 选了二阶精度,丢掉了单调性 — 所以阶跃处会振荡。

TVD 条件:Harten 不等式

Harten(1983)给出的出路是"总变差递减"的格式。

[equation]

左边衡量数值解的总波动量。每一步只要这个值不增加,就不会出现新的极值(上冲、下冲)。满足此条件的格式叫 TVD。

要绕过 Godunov 的墙,格式必须非线性化 — 算法要根据解的光滑程度改变形状。光滑区用二阶,陡梯度附近用一阶迎风。完成这个切换的就是 flux limiter。

一行读懂 Flux Limiter

Lax–Wendroff 的通量是一阶迎风加上修正项:

[equation]

其中 [math] 是对流速度,[math] 是单元宽度,[math] 是限制器,[math] 是前后斜率之比:

[equation]

光滑时 [math],极值附近 [math]L1[math]\varphi(r)$ 是一行函数,能在光滑区自动切到二阶,在极值附近切到一阶。
- minmod 稳,superbee 锐,van Leer / MC 平衡。LES 和激波捕获的选型标准并不相同。

---
Read more: https://cfdblog.cc/zh/posts/2026-04-24-flux-limiter-tvd-advection]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/2026-04-24-flux-limiter-tvd-advection</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/2026-04-24-flux-limiter-tvd-advection</guid>
      <pubDate>Fri, 24 Apr 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>알고리즘</category>
      <category>TVD</category>
      <category>flux-limiter</category>
      <category>advection</category>
      <category>수치해석</category>
    </item>
    <item>
      <title><![CDATA[水柱为何会断裂成水滴？—— Plateau–Rayleigh 不稳定性与碎裂机制]]></title>
      <description><![CDATA[表面张力将液柱雕琢成液滴的原理及喷雾设计的无量纲图谱

[4 min read · 1,761 words]]]></description>
      <content:encoded><![CDATA[import { PlateauRayleighJet } from '@/components/post-viz/2026-04-23-plateau-rayleigh-jet-breakup/PlateauRayleighJet'

试着将厨房的水龙头拧开一半。起初，水流是一根平滑的柱体。但从大约 10 厘米处开始，它就会断裂成规则的水滴。虽然这是每天都能看到的场景，但要回答为什么连续体户自发断裂并不容易。本文将追随 1849 年 Joseph Plateau 和 1879 年 Lord Rayleigh 给出的经典解释，并探讨在当今发动机喷嘴和喷墨设计中仍在使用的 韦伯数 (Weber number，惯性力/表面张力比) 和 奥内佐格数 (Ohnesorge number，粘性力/惯性与表面张力之积的平方根比) 如何扩展了这些结论。阅读完本文，你将能用一张机制图（Regime Map）回答“为什么有的射流会断裂成大水滴，而有的射流会像雾一样粉碎”。

为什么连续体选择断裂？

表面张力是一种倾向于减小表面积的力。对于等体积的液体，球形的表面积最小。因此，在无重力环境下，一团水会形成球体。

那么，对于等体积的长液柱和将其按一定间隔切开形成的液滴链，哪种情况的表面积更小呢？与直觉相反，液滴链的表面积更小 —— 但前提是切割间隔长于液柱的周长。这就是液柱自发碎裂的原因：这是向低能量状态演化的自然结果。

Plateau 的几何直觉

Plateau 计算了半径为 [math] 的圆柱体在受到轴向波长为 [math] 的微弱变形时表面积的变化。

[equation]

这里 [math] 是无量纲波数 [math]（波数 [math] 与半径的乘积）。如果该值小于 1，则 [math]，扰动会消散。

简单来说，该条件为：

$[math]kR[math]kR[math]kR[math]U = 1\,\text{m/s}[math]\lambda > 2\pi R[math]\lambda{\max} \approx 9 R[math]We[math]Oh[math]We$ 来控制目标液滴尺寸。

---
Read more: https://cfdblog.cc/zh/posts/2026-04-23-plateau-rayleigh-jet-breakup]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/2026-04-23-plateau-rayleigh-jet-breakup</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/2026-04-23-plateau-rayleigh-jet-breakup</guid>
      <pubDate>Thu, 23 Apr 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>流体力学</category>
      <category>流动现象</category>
      <category>Plateau-Rayleigh</category>
      <category>韦伯数</category>
      <category>奥内佐格数</category>
      <category>液柱碎裂</category>
    </item>
    <item>
      <title><![CDATA[选择 CFD 线性求解器：从 Jacobi 到 BiCGSTAB 的收敛速度对比]]></title>
      <description><![CDATA[通过代码和模拟对比 Krylov 子空间四大求解器的特性和收敛速度

[4 min read · 1,878 words]]]></description>
      <content:encoded><![CDATA[import { KrylovConvergence } from '@/components/post-viz/2026-04-22-cfd-linear-solvers-krylov/KrylovConvergence'

1952 年，Cornelius Lanczos、Magnus Hestenes 和 Eduard Stiefel 在一次学术会议上，偶然且独立地提出了同样的结果。那是一个仅需 [math] 次迭代即可求解对称正定 (SPD) 矩阵的算法。这就是我们今天所称的共轭梯度法 (Conjugate Gradient, CG)。有趣的是，70 年后的今天，CFD 求解器的核心依然鲜活地保留着这个想法——在 Krylov 子空间中寻找解。本文将通过 Python 和交互式模拟，对比 CFD 中最常用的四种求解器（Jacobi、Gauss-Seidel、CG 和 BiCGSTAB）的收敛速度。读完本文，你将能直接判断在实际工作中“针对该问题应选择哪种求解器”。

为什么 CFD 采用迭代法求解线性系统

对纳维-斯托克斯 (Navier–Stokes) 方程进行离散化后，每一步都会产生 [math] 形式的大型线性系统。其中 [math] 是系数矩阵，[math] 是单元中心变量矢量，[math] 是右侧源项。对于 100 万个单元的 3D 网格，[math] 将成为 [math] 大小的稀疏矩阵。在这种规模下，LU 分解（将矩阵分解为下三角和上三角乘积的直接法）会同时耗尽内存和 CPU。这就是 OpenFOAM、SU2、Gerris 等开源 CFD 代码无一例外使用迭代法 (iterative method) 的原因。

迭代法的基本思想很简单：从初始猜测值 [math] 出发，逐渐修正 [math]，直到残差 [math] 降至容差以下。问题在于如何定义“逐渐”。正是这个定义区分了不同求解器的名称。

Krylov 子空间的概念

初始残差 [math] 与矩阵 [math] 反复相乘后得到的矢量所构成的空间如下：

[equation]

[math] 即为 Krylov 子空间，[math] 为维数，[math] 为通过线性组合填充的空间。Krylov 系列求解器在 [math] 中寻找解，并使余下的残差 [math] 满足某种最优性条件。

将解限定在子空间内有两个优点：第一，除了矩阵-矢量乘法外没有其他运算，从而完整保留了稀疏结构；第二，理论上可以在该子空间内提取出最优解。CG 在 Krylov 空间内精确地使 A-范数误差最小化，而 GMRES 则使 2-范数残差最小化。

四种求解器的特性对比

| 求解器 | 矩阵要求 | 内存占用 | 优点 | 缺点 |
|------|-----------|--------|------|------|
| Jacobi | 推荐对角占优 | 极低 | 易于并行化，10 行代码实现 | 慢（谱半径 [math]） |
| Gauss-Seidel | 任意 | 极低 | 比 Jacobi 快约 2 倍 | 本质上是串行的，不利于 GPU |
| CG | 必须为 SPD | 4 个矢量 | 对 SPD 最优，三项递推，轻量级 | 不支持非对称矩阵 |
| BiCGSTAB | 任意 | 7 个矢量 | 支持非对称，无需转置 | 收敛过程有波动，可能出现停滞 (break-down) |

对于压力泊松方程 [math]，由于其具有 SPD 特性，CG 是标准选择。而包含平流-扩…

---
Read more: https://cfdblog.cc/zh/posts/2026-04-22-cfd-linear-solvers-krylov]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/2026-04-22-cfd-linear-solvers-krylov</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/2026-04-22-cfd-linear-solvers-krylov</guid>
      <pubDate>Wed, 22 Apr 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>算法</category>
      <category>线性求解器</category>
      <category>Krylov</category>
      <category>数值分析</category>
    </item>
    <item>
      <title><![CDATA[在 O(N log N) 内求解壁面距离：Eikonal 方程与快速行进法]]></title>
      <description><![CDATA[RANS 湍流模型必需的壁面距离输入及其高效计算算法

[5 min read · 2,378 words]]]></description>
      <content:encoded><![CDATA[import { EikonalFrontPropagation } from '@/components/post-viz/2026-04-22-wall-distance-eikonal-fast-marching/EikonalFrontPropagation'

1996年，加州大学伯克利分校的 James Sethian 正在完善一种用于追踪医学影像中血管边界的算法。其成果——快速行进法（Fast Marching Method），如今却在一些意想不到的地方发挥着作用。每当 RANS（雷诺平均纳维-斯托克斯）求解器在飞机机翼周围运行时，正是这种算法在为每个网格点生成壁面距离（wall distance）。Spalart-Allmaras 模型和 k-ω SST 模型都要求将“最近的壁面在哪里”这一数值作为每个网格的输入。本文将总结朴素求解方法的成本、将问题转化为 Eikonal 方程（形式为 |∇d|=1/F 的双曲型 PDE）的思想，以及如何利用 Dijkstra 算法的连续版——快速行进法，在 [math] 时间内获得解。

为什么湍流模型需要壁面距离

边界层湍流的统计量强烈依赖于距壁面的距离 [math]。RANS 模型通过代数式引入这种依赖性。Spalart-Allmaras 模型在破坏（destruction）项中直接使用 [math]（壁面距离）。k-ω SST 模型则在混合函数 [math] 中包含 [math]。在与 LES 的混合模型（DES, DDES, IDDES）中，壁面距离也起着开关的作用。

问题在于，[math] 是网格的几何量。如果网格发生移动或变形，则需要在每个时间步重新计算。旋转机械（压缩机、泵）中转子-定子边界存在相对运动的情况就属于此类。

朴素方法的陷阱

直观的想法是“计算每个单元到所有壁面的距离并取最小值”。实际上，教科书中的示例通常采用这种方法。

其计算成本为 [math]。假设求解整架飞机，如果有 10M 个单元和 0.5M 个壁面，则需要进行 5 万亿次距离计算。如果每个时间步都运行一次，仿真将永远无法完成。虽然使用 KD-tree 等空间数据结构可以将成本降低到 [math]，但对于复杂形状的壁面邻近查询，负担依然沉重。

转变思路：Eikonal 方程

我们将壁面距离视为 PDE 的解。一个“在壁面处为 0，且在所有方向上梯度模长均为 1”的函数正是距离场。

[equation]

这里，[math] 是到达壁面的“时间”，[math] 是传播速度（默认取 1），[math] 是壁面集合。固定 [math]，则 [math] 就是欧几里得距离。

该方程是双曲型的（hyperbolic）。信息沿特征线（从壁面延伸出的直线）单向流动。这种单向性是高效算法的关键。利用“值仅从已确定的点传入”这一性质，每个点仅需访问一次。

快速行进法：连续版 Dijkstra

Sethian 的思想可以概括为两步：

1. 将所有网格点分为三类集合：已接受（Accepted）、待考虑（Considered）和远处（Far）。
2. 从待考虑集合中找出到达时间最小的点，将其转入已接受集合，并更新其邻居。

为了快速取出最小值，使用最小堆（min-heap）是很自然的。这与图最短路径算法 Dijkstra 的结构相同。区别在于邻居的更新方式。在图中是简单的加法，而在 Eikonal 方程中，需要求解上风（upwind）二次方程来获得值。

在 2D 结构化网格中，更新公式如下：

[equati…

---
Read more: https://cfdblog.cc/zh/posts/2026-04-22-wall-distance-eikonal-fast-marching]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/2026-04-22-wall-distance-eikonal-fast-marching</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/2026-04-22-wall-distance-eikonal-fast-marching</guid>
      <pubDate>Wed, 22 Apr 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>算法</category>
      <category>Eikonal</category>
      <category>Fast-Marching</category>
      <category>网格</category>
    </item>
    <item>
      <title><![CDATA[昆虫在蜂蜜中游泳 —— 雷诺数改变的流动世界]]></title>
      <description><![CDATA[通过无量纲化揭示的雷诺数，以及尺度如何产生流动的差异

[4 min read · 1,961 words]]]></description>
      <content:encoded><![CDATA[细菌无法游泳。准确地说，我们所谓的“游泳”——即基于惯性的推进方式——对细菌并不奏效。不像我们通过摆动尾巴利用惯性前进，细菌生活在一个惯性消失的世界——一个就像透明蜂蜜一样的地方。这篇博文将探讨为什么同样的纳维-斯托克斯 (Navier–Stokes) 方程会因尺度不同而创造出完全不同的世界，以及汇总这种差异的单一数字——雷诺数 (Reynolds Number，惯性力/粘性力比) 是如何成为流体力学“隐藏语法”的。最后，我们还会讨论为什么无量纲化（脱掉方程的单位外壳，只留下结构的操作）是流体力学的第一语法。

同样的方程，不同的世界

蓝鲸在海洋中游泳。水分子的本质当然是一样的。但是对于 1 μm 的细菌来说，水感觉就像是完全不同的物质。这是因为即使使用同样的纳维-斯托克斯方程，一旦尺度发生变化，主导项也会随之改变。

不可压缩纳维-斯托克斯方程如下所示：

[equation]

其中 [math] 是密度，[math] 是速度场，[math] 是压力，[math] 是粘性系数。左边代表惯性（质量 × 加速度），右边的 [math] 是粘性（内部摩擦）项。这两股力量时刻在博弈。谁会赢呢？

脱掉方程的外衣：无量纲化

答案由尺度决定。为了证明这一点，必须对方程进行无量纲化。我们用特征长度 [math]、特征速度 [math]、特征时间 [math]、特征压力 [math] 来除以所有的量。

[equation]

每一个变量的含义是“用物理量自身自然的量级测得的值”。将这些定义代入纳维-斯托克斯方程并整理，就会剩下一个单位全部消失的整洁公式。

[equation]

所有的物理单位都消失了，只剩下唯一的数字 [math]。这就是雷诺数。

[equation]

[math] 是运动粘度 (kinematic viscosity)。[math]、[math]、[math] 越大，惯性越占上风；[math] 越大，粘性越占上风。即使在同样的水中，如果 [math] 减小，[math] 会线性下降。最终，主导世界的项会发生改变。

尺度改变雷诺数

让我们通过数字来感受一下。以水的运动粘度 [math] 为基准，代表性生物的 [math] 如下：

[code block]

最大值和最小值之间相差竟达 13 个数量级。而且是在同样的水里。雷诺数不仅仅是一个简单的数字，它是在流体内部对不同“世界”进行标记的地址。

在像细菌这样 [math] 的领域，无量纲方程的惯性项实际上消失了，方程两边乘以 [math] 就变成了 斯托克斯 (Stokes) 方程 [math]。没有时间导数项。也就是说，细菌周围的流动“无法记住过去”。撤去力量的瞬间，速度也会变为零。

通过可视化建立直觉

在下面的模拟中，请亲自尝试操纵雷诺数。

如果将雷诺数降低到 10 左右，矢量场会像梳子一样整齐。这是因为粘性会迅速消散所有的扰动。相反，如果增加到 1000，矢量会开始不规则地晃动。这就是湍流的征兆。

下面是圆柱背后的流动。观察重点是 卡门涡街 (Von Kármán vortex street)（从圆柱后部周期性脱落的涡旋）是否形成。

在 [math] 时，圆柱后部流动是左右对称附着的。一旦超过 40，上下方的涡旋会交替脱落，呈现出“尾巴周期性摆动”的图案。旗帜飘扬、电线啸叫、长桥在风中震动，原因都是卡门涡街。自然现象的频率与斯特劳哈尔数 (Strouhal number) [math] 相关，只要知道 [math] 和 [math]，甚至可以估算出啸叫声的…

---
Read more: https://cfdblog.cc/zh/posts/2026-04-21-reynolds-number-scale-fluid-mechanics]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/2026-04-21-reynolds-number-scale-fluid-mechanics</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/2026-04-21-reynolds-number-scale-fluid-mechanics</guid>
      <pubDate>Tue, 21 Apr 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>流体力学</category>
      <category>流动现象</category>
      <category>雷诺数</category>
      <category>无量纲化</category>
    </item>
    <item>
      <title><![CDATA[不连续伽辽金法 (DGM)：非结构网格压缩流动分析的高精度离散化]]></title>
      <description><![CDATA[从 DGM 弱形式推导到高斯积分及非结构网格实现的逐步总结

[3 min read · 1,347 words]]]></description>
      <content:encoded><![CDATA[import { DGElementBasis } from '@/components/post-viz/2026-04-20-discontinuous-galerkin-method-cfd/DGElementBasis'

不连续伽辽金法 (Discontinuous Galerkin Method, DGM) 是一种结合了有限元法 (FEM) 和有限体积法 (FVM) 优点的数值计算方法。它在单元内部使用高阶多项式基函数，并在单元边界处通过数值通量交换信息。对于非结构网格上的高精度压缩流动分析，它是一个非常有力的选择。

控制方程与通量分离

压缩流动的守恒方程：

[equation]

其中：
- [math]：守恒变量矢量
- [math]：对流 (convective) 通量
- [math]：粘性 (viscous) 通量
- [math]：源项

基函数展开与弱形式推导

在单元 [math] 内部，将解近似为基函数的线性组合：

[equation]

[math] 是单元内的自由度数，由近似多项式阶数 [math] 决定（在 3D 中，[math]）。

乘以测试函数 [math] 并在 [math] 上积分：

[equation]

应用格林公式（分部积分），将其分为体积分和边界积分：

[equation]

边界上的 [math] 是利用相邻单元信息得到的数值通量（如 Roe, HLLC 等）。

质量矩阵与时间积分

整理为关于第 [math] 个基函数系数的常微分方程 (ODE)：

[equation]

其中质量矩阵 (mass matrix) 为：

[equation]

使用正交基函数（如泰勒基或勒让德多项式等）可以使 [math] 成为对角矩阵，从而消除逆矩阵的计算成本。残差矢量 [math] 是体积分项和面通量项之和：

[equation]

高斯积分的应用

体积分和面积分使用高斯-勒让德 (Gauss-Legendre) 积分法进行数值计算。为了精确积分 [math] 阶多项式，至少需要 [math] 阶以上的积分。

各单元类型的高斯点数量（按代表性阶数）：

| 单元类型   | 1阶 | 2阶 | 3阶 |
|-----------|-----|-----|-----|
| 四面体 (Tetrahedron) | 1  | 4   | 10  |
| 六面体 (Hexahedron)  | 1  | 8   | 27  |
| 棱柱 (Prism)       | 3  | 9   | 18  |
| 棱锥 (Pyramid)     | 1  | 5   | 15  |

对于面 (face) 类型，使用单元点的 3 倍（3D 投影）。

算法实现步骤

在实际实现中，按以下顺序进行：

1. 单元/面分类：四面体/六面体/棱柱/棱锥/多面体
2. 基函数准备：计算适合各单元类型 × 近似阶数的 [math]
3. 高斯点缓存：将参考单元 (reference element) 的坐标和权重存储在内存中
4. 变量初始化：设置 [math]（如自由流条件等）
5. 循环（时间推进）：
   - 体积分：[math] — 在每个高斯点计算通量后累加
   - 面通量：[math] — 计算数值通量
   - RK 更新：SSP-RK3 等显式时间积分

[code block]

数值通量选择 — 实践注意事项

在 DGM 中，数值通量直接关系到稳定性和精度。

- Roe 通量：…

---
Read more: https://cfdblog.cc/zh/posts/2026-04-20-discontinuous-galerkin-method-cfd]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/2026-04-20-discontinuous-galerkin-method-cfd</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/2026-04-20-discontinuous-galerkin-method-cfd</guid>
      <pubDate>Mon, 20 Apr 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>FEM</category>
      <category>DGM</category>
      <category>高阶精度</category>
      <category>压缩流动</category>
    </item>
    <item>
      <title><![CDATA[刚体动力学中的有限元法：基于四元数的旋转处理与惯性张量]]></title>
      <description><![CDATA[在有限元刚体模拟中利用四元数表示旋转并处理惯性张量的方法

[2 min read · 974 words]]]></description>
      <content:encoded><![CDATA[import { QuaternionRotationDemo } from '@/components/post-viz/2026-04-20-fem-rigid-body-dynamics-quaternion/QuaternionRotationDemo'

刚体动力学的基本方程

在流固耦合 (FSI) 分析或离散元 (DEM) 模拟中，准确描述刚体的运动至关重要。刚体是一种不发生变形的物体，其内部任意两点之间的距离始终保持不变。

刚体内任意粒子 [math] 的速度可以分解如下：

[equation]

其中 [math] 是质心的速度，[math] 是角速度，[math] 是从质心到粒子 [math] 的位移矢量。

线动量与角动量

根据牛顿第二定律，总线动量为：

[equation]

其中 [math] 是总质量。质心的加速度为：

[equation]

总角动量为：

[equation]

其中 [math] 是惯性张量 (inertia tensor)，[math] 是总力矩 (torque)。

惯性张量

相对于质心的惯性张量定义为：

[equation]

扩展到连续体：

[equation]

其中 [math] 是单位张量，[math] 是外积 (outer product)。

当物体旋转时，惯性张量会通过方位矩阵 (orientation matrix) [math] 进行变换。

[equation]

其中 [math] 是在物体坐标系 (body frame) 下的初始惯性张量，只需在模拟开始时计算一次。

使用四元数表示旋转

使用欧拉角 (Euler angles) 表示旋转会产生万向节死锁 (gimbal lock) 问题。为了避免这种情况，我们使用四元数 (quaternion)。

四元数 [math] 由标量部分和矢量部分组成。

[equation]

绕单位轴 [math] 旋转角度 [math] 的四元数为：

[equation]

两个四元数 [math] 和 [math] 的复合旋转可以用它们的乘积表示。

[equation]

利用四元数，方位矩阵 [math] 可以显式地用四元数分量表示。

[equation]

四元数的时间导数与角速度 [math] 相关联。

[equation]

有限元离散化与四面体形函数

在有限元法 (FEM) 中离散刚体的位移场时，四面体单元的形函数 (shape function) 为：

[equation]

其中 [math] 是无量纲体心坐标 (barycentric coordinates)，满足 [math]。

在线性四面体单元中，位移插值为：

[equation]

应用刚体约束条件后，自由度减少为 6 个（3 个平移 + 3 个旋转）。

Python 实现示例

[code block]

实践注意事项

1. 遗忘四元数归一化
随着数值积分的进行，会出现 [math] 的情况，导致旋转矩阵变为非正交矩阵。必须在每个时间步执行 q /= norm(q)。

2. 惯性张量的坐标系混淆
[math] 是在物体固定坐标系 (body frame) 下定义的。如果在世界坐标系 (world frame) 下计算出力矩，则必须先转换为 [math] 后再应用。

3. 时间步选择
为了保证数值稳定性，对于刚体的最高固有频率 [math]，需要满足条件 $\Delta t

---
Read more: https://cfdblog.cc/zh/posts/2026-04-20-fem-rigid-body-dynamics-quaternion]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/2026-04-20-fem-rigid-body-dynamics-quaternion</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/2026-04-20-fem-rigid-body-dynamics-quaternion</guid>
      <pubDate>Mon, 20 Apr 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>FEM</category>
      <category>刚体动力学</category>
      <category>四元数</category>
    </item>
    <item>
      <title><![CDATA[Dean 流：螺旋管中的二次流解析解与 CFD 验证]]></title>
      <description><![CDATA[弯曲管道中离心力产生的 Dean 涡旋 —— 从解析解推导到数值验证

[3 min read · 1,619 words]]]></description>
      <content:encoded><![CDATA[import { DeanSecondaryFlow } from '@/components/post-viz/2026-03-28-dean-flow-analytical-solution/DeanSecondaryFlow'

在螺旋管式直流蒸气发生器（Helical Steam Generator）的设计中，有一个绕不开的问题：
“与直管相比，它的传热性能提高了多少？”
这个问题的核心在于 Dean 涡旋（Dean vortices） —— 这是一对由弯曲管道中的离心力产生的螺旋状二次流。

这种流动最早由 W. R. Dean 在 1928 年描述，是核工程、化学工程和生物力学领域反复出现的经典问题。今天，我们将直接推导 Dean 的扰动展开式，使用 Python 进行可视化，并利用有限差分法进行数值验证。

---

1. 问题设置

考虑一个曲率半径为 [math] 的圆弧形管道（管道半径为 [math]）。在管道截面上建立极坐标系 [math]，并定义 [math] 为沿管道轴线的弧长坐标。

[equation]

在曲线坐标系下表达不可压缩 Navier-Stokes 方程，轴向动量方程中会增加一个离心力项。

[equation]

如果没有离心力（[math]），该方程将直接退化为 Poiseuille 流。

---

2. 解析解推导

2-1. 无量纲化

使用特征速度 [math]（Poiseuille 流中心速度）进行无量纲化：

[equation]

零阶解（Poiseuille 流）为：

[equation]

2-2. Dean 数的定义

Dean 引入了以下无量纲数：

[equation]

在现代文献中，也常基于管径 [math] 来定义：

[equation]

2-3. 扰动展开 (Dean 1928)

在 [math] 的条件下，将流函数 [math] 按 [math] 进行展开：

[equation]

一阶二次流流函数为：

[equation]

二次流速度分量（由 [math] 推导）：

[equation]

轴向速度的一阶修正：

[equation]

最终轴向速度（二阶近似）：

[equation]

---

3. 物理意义

- 二次流：具有 [math] 相关性 —— 流体被推向外侧（outer wall，[math]）并从两侧返回，形成一对涡旋。
- 轴向速度畸变：受离心力影响，高流速核心向外侧偏移，导致速度分布不对称。
- 剪切应力增大：二次流扰动了边界层，从而显著提高了传热系数（Nusselt 数 ↑）。

传热增强关联式（对比 Dittus-Boelter）：

[equation]De = Red\sqrt{\frac{d}{2R}} = Red\sqrt{\frac{0.012}{2 \times 2.3}} \approx 0.051 \cdot Red$[math]Red \approx 10,000[math]De \approx 510$。
在此区域内，Dean 涡旋充分发育，传热系数较直管提高 3060%。

然而，当伴随沸腾（boiling）时情况会发生变化 —— 离心力会将气泡推向管内侧壁（inner wall），导致局部含气率（void fraction）分布不均。这是导致 DNB（偏离核态沸腾）预测困难的核心原因。一维关联式失效的原因正是因为这种三维二次流的存在。

---

延伸阅读

- Dean, W. R. (1928…

---
Read more: https://cfdblog.cc/zh/posts/2026-03-28-dean-flow-analytical-solution]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/2026-03-28-dean-flow-analytical-solution</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/2026-03-28-dean-flow-analytical-solution</guid>
      <pubDate>Sat, 28 Mar 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>解析解</category>
      <category>古典流体力学</category>
      <category>CFD验证</category>
      <category>Dean流</category>
      <category>二次流</category>
      <category>螺旋管</category>
    </item>
    <item>
      <title><![CDATA[泊肃叶流动：解析解推导与有限差分验证]]></title>
      <description><![CDATA[最简单的粘性流动的完整解析解推导，并使用有限差分代码验证数值精度的 CFD 入门标杆案例。

[3 min read · 1,335 words]]]></description>
      <content:encoded><![CDATA[import { PoiseuilleProfile } from '@/components/post-viz/2026-03-28-poiseuille-flow-analytical-solution/PoiseuilleProfile'

泊肃叶流动（Poiseuille flow）是由恒定压力梯度驱动的，在两个平行平板之间或圆管内部的完全发展层流。
由于存在精确的解析解，它作为 CFD 代码验证的首选测试案例，出现在全球各种流体力学教科书中。

今天，我们将以通道流动（2D 平行板之间）为对象，分步骤推导其解析解，并编写简单的有限差分（FD）代码来验证其收敛阶。

问题设置

几何形状与边界条件

考虑两个无限大平行平板之间的完全发展层流。

- 通道半宽：[math]（平板位于 [math] 处）
- 流动方向：[math]（假设无限长）
- 边界条件：两壁面无滑移（no-slip）[math] [math]
- 驱动力：恒定压力梯度 [math] 为常数）

统领方程

由于是完全发展流动，[math] 且 [math]。[math] 方向的 Navier–Stokes 方程为：

[equation]

应用完全发展条件（[math]）：

[equation]

解析解推导

第一步：简化为常微分方程 (ODE)

[equation]

第二步：一次积分

[equation]

第三步：二次积分

[equation]

第四步：应用边界条件

[math]:

[equation]

[math]:

[equation]

(1) [math] (2): [math]（对称性）

(1) [math] (2): [math]

最终解析解

[equation]

通道中心（[math]）处最大速度：

[equation]

物理意义

速度剖面

解析解呈抛物线（parabola）分布。壁面摩擦均匀地传递到整个流动截面，导致中心流速最大，壁面流速为零。

无量纲速度 [math] 是一个通用剖面，与通道半宽 [math] 或粘度 [math] 无关。

壁面剪切应力

[equation]

（大小：[math]）压力梯度越大，通道越宽，壁面摩擦力越大。

体积流量

[equation]

这被称为 Hagen-Poiseuille 定律 的 2D 版本。由于流量与 [math] 成正比，通道宽度增加一倍，流量将增加八倍。

使用 Python 进行解析解可视化

[code block]

有限差分法数值验证

使用二阶中心差分格式对 [math] 进行离散化。在均匀网格 [math] 上：

[equation]

边界条件：[math]。

将其写成三对角（tridiagonal）线性方程组：

[equation]

Python 实现

[code block]

收敛结果

| [math] | [math] | [math] 误差 | 收敛阶 |
|----:|-----------|------------|----------|
| 4 | 0.4000 | 2.78e-16 | — |
| 8 | 0.2222 | 1.67e-16 | 2.0 |
| 16 | 0.1176 | 2.22e-16 | 2.0 |
| 32 | 0.0606 | 2.78e-16 | 2.0 |
| 64 | 0.0308 | 2.22e-16 | 2.0 |

> 注：由于泊肃叶流动是二次多项式分布，因此使用二…

---
Read more: https://cfdblog.cc/zh/posts/2026-03-28-poiseuille-flow-analytical-solution]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/2026-03-28-poiseuille-flow-analytical-solution</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/2026-03-28-poiseuille-flow-analytical-solution</guid>
      <pubDate>Sat, 28 Mar 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>解析解</category>
      <category>古典流体力学</category>
      <category>CFD验证</category>
      <category>泊肃叶流动</category>
      <category>有限差分</category>
    </item>
    <item>
      <title><![CDATA[[CFD Q&A] 当 simpleFoam 压力残差无法收敛时]]></title>
      <description><![CDATA[解决 SIMPLE 算法发散的实战记录 —— 关键在于松弛因子的设置

[2 min read · 1,097 words]]]></description>
      <content:encoded><![CDATA[import { SimpleResidualHistory } from '@/components/post-viz/2026-03-27-simpleFoam-pressure-divergence/SimpleResidualHistory'

上周遇到了一个非常耗时的问题。在运行 simpleFoam 时，压力残差（pressure residual）始终无法降至 1e-3 以下，反而开始上升。起初我以为是网格问题，但最终发现症结在于松弛因子（relaxation factor）。

问题现象

- 软件: OpenFOAM v2312
- 几何: 2D 矩形通道，inlet–outlet 边界
- 湍流模型: k-ε (standard)
- 求解器: simpleFoam (稳态)

在前 2030 次迭代（iteration）中，收敛情况良好，但随后压力残差突然开始跳动。

[code block]

速度（velocity）收敛良好，但压力（pressure）始终不稳定。这是典型的压力-速度耦合不稳定性表现。

原因分析过程

第一步：检查网格质量

首先运行 checkMesh。

[code block]

最大非正交性（non-orthogonality）为 32 度，最大扭曲度（max skewness）为 0.8 —— 表现尚可。看来网格不是主要问题。

第二步：检查边界条件

入口（inlet）压力设为 zeroGradient，出口（outlet）设为 fixedValue 0。这是标准设置，没有问题。

但在检查初始 p 场时，发现入口处存在异常大的数值。这是之前使用 funkySetFields 进行实验后留下的残留值。

第三步：检查 fvSolution

[code block]

U=0.9 是一个相当激进的数值。在 SIMPLE 算法中，提高速度松弛可以加快收敛，但如果压力更新跟不上，就会导致发散。

两个原因叠加导致了发散：
1. 松弛因子设置过高
2. 初始 p 场中存在错误的残留值

解决方案

降低松弛因子

[code block]

初次运行算例时，建议从保守的数值开始。确认收敛后，再逐渐提高。

初始化 p 场

[code block]

或者直接打开 0/p 文件，将 internalField 设置为 uniform 0;。

[code block]

验证

修改后重新运行，结果如下：

[code block]

在迭代 200 次左右时，压力残差稳定降至 1e-4 水平。

经验总结

simpleFoam 收敛检查清单 —— 按此顺序检查可解决大部分问题：

1. 首查初始条件：确认 0/ 目录下的 p、U 场是否符合预期。如果存在旧实验残留，务必初始化。

2. 松弛因子要保守：首次运行建议使用 U=0.7, p=0.3 的默认值。安全确认收敛后再提速。尤其是 p 的松弛因子应保持较低，以稳定 SIMPLE 循环。

3. 区分速度与压力收敛：如果 U 残差低而 p 发散，通常是松弛因子的问题。如果两者都发散，应先检查网格或边界条件。

4. 观察 GAMG 迭代次数：如果在同一次外迭代中，求解 p 所需的内迭代次数突然增加，说明收敛方向可能出现了偏差。

由于压力修正循环的特性，SIMPLE 算法对松弛因子非常敏感。初次运行应始终保持保守 —— 虽然起步慢，但确保稳定收敛后再加速，最终效率反而更高。

---

如果你也遇到了类似的问题，欢迎在评论区分享你的环境（版本…

---
Read more: https://cfdblog.cc/zh/posts/2026-03-27-simpleFoam-pressure-divergence]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/2026-03-27-simpleFoam-pressure-divergence</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/2026-03-27-simpleFoam-pressure-divergence</guid>
      <pubDate>Fri, 27 Mar 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>CFD实战</category>
      <category>QA</category>
      <category>OpenFOAM</category>
      <category>SIMPLE</category>
      <category>收敛</category>
    </item>
    <item>
      <title><![CDATA[[OpenFOAM 教程] 后步台阶流动分析 — 利用 simpleFoam 捕捉再循环区域]]></title>
      <description><![CDATA[使用 OpenFOAM simpleFoam 逐步分析后步台阶 (Backward Facing Step) 不可压缩流动的指南

[2 min read · 926 words]]]></description>
      <content:encoded><![CDATA[import { BFSRecirculation } from '@/components/post-viz/2026-03-26-openfoam-backward-facing-step/BFSRecirculation'

在本教程中，我们将使用 simpleFoam 模拟 后步台阶 (Backward Facing Step) 几何形状中的再循环流动。目标是直接观察台阶下游形成的再循环区域 (recirculation zone) 和再附着点 (reattachment point)。

---

前提条件

- OpenFOAM 版本: v2312 或更高版本 (OpenFOAM.com 或 OpenFOAM.org 均可)
- 预备知识: 基本终端命令，理解 OpenFOAM 案例结构 (0/constant/system)
- 所需软件: ParaView 5.x 或更高版本 (结果可视化)

---

第 1 步：创建案例目录

[code block]

案例结构如下：

[code block]

[code block]

---

第 2 步：网格生成 — blockMeshDict

system/blockMeshDict 通过长方体块的组合定义台阶形状。下面是一个简化的 2D 案例示例 (台阶高度 H = 0.1 m)。

[code block]

[code block]

预期输出:
[code block]

---

第 3 步：设置边界条件

0/U — 速度边界条件

[code block]

0/p — 压力边界条件

[code block]

0/k — 湍动能

[code block]

---

第 4 步：设置物性参数和湍流模型

constant/transportProperties

[code block]

constant/turbulenceProperties

[code block]

---

第 5 步：设置数值方案和求解器

system/fvSchemes

[code block]

system/fvSolution

[code block]

---

第 6 步：执行分析

[code block]

预期输出 (收敛过程):
[code block]

收敛标准是所有变量的残差 (residual) 均低于 1e-4。

---

第 7 步：结果可视化 (ParaView)

[code block]

在 ParaView 中按以下顺序查看结果：

1. Coloring 下拉菜单 → 选择 U → 使用 Magnitude 显示速度大小
2. 添加 Glyph 过滤器 → 可视化矢量方向 (确认再循环区域)
3. Stream Tracer 过滤器 → 绘制流线

使用 foamToVTK 转换文件后的后处理：

[code block]

使用 Python 自动提取再附着长度：

[code block]

---

常见错误及解决办法

错误 1: FOAM FATAL ERROR: Cannot find file "0/epsilon"

[code block]

原因: 缺少 0/epsilon 文件。
解决办法: 使用与 k 文件相同的格式创建 0/epsilon。

[code block]

---

错误 2: 分析发散 (Floating point exception)

[code block]

原因: 松弛因…

---
Read more: https://cfdblog.cc/zh/posts/2026-03-26-openfoam-backward-facing-step]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/2026-03-26-openfoam-backward-facing-step</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/2026-03-26-openfoam-backward-facing-step</guid>
      <pubDate>Thu, 26 Mar 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>OpenFOAM</category>
      <category>教程</category>
      <category>simpleFoam</category>
      <category>后步台阶</category>
      <category>湍流</category>
    </item>
    <item>
      <title><![CDATA[通过可视化理解 Reynolds 数与流动转捩]]></title>
      <description><![CDATA[通过交互式可视化理解 Reynolds 数与层流-湍流转捩现象

[2 min read · 904 words]]]></description>
      <content:encoded><![CDATA[什么是 Reynolds 数

理解流体流动时最重要的无量纲数之一是 Reynolds 数(Re)。它表示惯性力与粘性力之比。

[equation]

其中:
- [math]: 流体密度 [math]
- [math]: 特征速度 [math]
- [math]: 特征长度 [math]
- [math]: 动力粘度 [math]
- [math]: 运动粘度 [math]

流动状态划分

| Reynolds 数范围 | 流动状态 | 特征 |
|------------------|-----------|------|
| [math] | 蠕动流(Stokes flow) | 粘性主导,完全层流 |
| [math] | 湍流 (Turbulent) | 不规则混合,高能量耗散 |

流动转捩的物理机制

从层流到湍流的转捩始于开尔文-亥姆霍兹(Kelvin-Helmholtz)不稳定性。在存在速度梯度的边界上,小扰动放大形成涡(vortex),进而引发能量级串。

速度剖面的变化由 Navier-Stokes 方程描述:

[equation]

左边的非线性项 [math] 承担惯性,右边的 [math] 承担粘性衰减。Reynolds 数表示这两项的相对大小。

速度场可视化:Reynolds 数下的流动变化

通过下方模拟直接查看 Reynolds 数变化对速度场的影响:

观察要点:
- 低 Re (Re ≈ 150): 矢量平滑而规则 — 粘性立即抑制扰动
- 中 Re (Re ≈ 100500): 障碍物尾流出现非对称性 — 惯性力与粘性力相当
- 高 Re (Re > 1000): 矢量方向变得不规则,涡结构发育

圆柱绕流流线:卡门涡街

圆柱(cylinder)绕流中 Reynolds 数增加时,会出现周期性涡脱落,即卡门涡街(Kármán vortex street)。

脱落频率用 Strouhal 数 [math] 归一化:

[equation]

其中 [math] 为涡脱落频率,[math] 为圆柱直径,[math] 为来流速度。圆柱情况下 math离散此 Navier-Stokes 方程,并比较迎风差分与中心差分格式对精度的影响。

---
Read more: https://cfdblog.cc/zh/posts/2026-03-25-reynolds-flow-transition-visualization]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/2026-03-25-reynolds-flow-transition-visualization</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/2026-03-25-reynolds-flow-transition-visualization</guid>
      <pubDate>Wed, 25 Mar 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>시각화</category>
      <category>Reynolds</category>
      <category>유동천이</category>
      <category>유체역학</category>
    </item>
    <item>
      <title><![CDATA[[论文回顾] Physics-Informed Neural Networks for Turbulence Modeling]]></title>
      <description><![CDATA[一种利用将物理定律直接嵌入损失函数的神经网络，从稀疏数据中重构流场的新方法

[2 min read · 1,220 words]]]></description>
      <content:encoded><![CDATA[import { PINNLossLandscape } from '@/components/post-viz/2026-03-24-paper-review-pinn-turbulence-modeling/PINNLossLandscape'

论文信息

- 作者: Raissi, M., Perdikaris, P., Karniadakis, G. E.
- 期刊: Journal of Computational Physics, Vol. 378, pp. 686–707, 2019
- DOI: 10.1016/j.jcp.2018.10.045
- arXiv: 1711.10561

---

一句话总结

该论文提出了一种通过将 Navier-Stokes 方程直接嵌入（Physics-Informed）神经网络损失函数的方法，实现仅通过几个压力传感器即可反求整个速度场。

---

研究背景

传统的 CFD 处于两个极端之间。

传统方法 (k-ε, k-ω SST): 依赖于经验闭合系数。当雷诺数或几何形状发生变化时，需要重新调整系数，泛化能力有限。

纯数据驱动的深度学习: 需要大量的标注数据，且训练好的模型无法保证质量守恒或动量守恒。即使预测结果在物理上完全讲不通，损失函数也无法感知。

PINNs 是弥合这一差距的尝试。即使数据稀疏，物理定律也能起到正则化（regularizer）的作用。

---

核心方法论

PINN 的总损失函数是两项之和：

[equation]

数据损失 [math] 是观测值（例如压力传感器）与神经网络预测值之间的差异。

物理损失 [math] 是不可压缩 Navier-Stokes 方程的残差（residual）：

[equation]

第二项是连续性方程（质量守恒）。由于神经网络被训练为使该残差趋于 0，因此预测值始终近似满足 N-S 方程。

导数是通过 PyTorch/TensorFlow 的自动微分 (automatic differentiation) 计算的，不需要额外的数值离散化。

---

主要结果

| 案例 | 条件 | 结果 |
|--------|------|------|
| 2D 圆柱绕流 | Re=100, 仅使用压力传感器 | 速度场重构误差  一句话点评: "定义了 CFD 与深度学习交点的论文。虽然目前无法替代 OpenFOAM，但在反问题和稀疏数据重构方面已经具有实用价值。"

调节 λPDE / λBC / λdata，立刻看到 PINN 损失权衡的脆弱性。

---
Read more: https://cfdblog.cc/zh/posts/2026-03-24-paper-review-pinn-turbulence-modeling]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/2026-03-24-paper-review-pinn-turbulence-modeling</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/2026-03-24-paper-review-pinn-turbulence-modeling</guid>
      <pubDate>Tue, 24 Mar 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>논문리뷰</category>
      <category>PINN</category>
      <category>딥러닝</category>
      <category>난류모델</category>
    </item>
    <item>
      <title><![CDATA[Mach Architect: 通过设计喷管学习可压缩流]]></title>
      <description><![CDATA[通过直接调节缩放喷管的几何形状和背压,体验等熵流、阻塞和正激波的交互式模拟器。

[1 min read · 741 words]]]></description>
      <content:encoded><![CDATA[Mach Architect

只通过教科书学习缩放(C-D)喷管流动时,根据面积比 [math] 与背压比 [math] 的流动状态变化只看图很难形成直觉。

亲手设计喷管,转动背压旋钮。 通关 4 个关卡即可掌握 1D 可压缩喷管流的核心。

---

---

操作方法

- 喷管形状: 在 SVG 上拖动蓝色控制点(control point)上下调整截面积
- 背压: 右侧滑块调节 [math]
- 关卡选择: 上方 LV1LV4 按钮切换

---

关卡解析

Level 1: 亚音速加速

最基础的问题。在收缩喷管中,亚音速流动随截面减小而加速。
等熵关系式:

[equation]

由于 [math],[math] 减小时 [math] 增大。目标是出口马赫数 0.450.55。

Level 2: 阻塞

流动阻塞(choke)时喉部 [math]。此状态下继续降低背压不会改变喉部上游的质量流量。

临界压力比 ([math]):

[equation]

将背压降至该值以下,或将喉部做得足够窄。

Level 3: 超音速喷管设计

C-D 喷管中,喉部之后截面再次扩大就会加速到超音速。要达到 [math]:

[equation]

并将背压降至设计压力(Pbdesign),才能形成无激波的完全超音速流。

Level 4: 激波定位

背压高于设计压力但低于临界压力时,喷管内部会出现正激波(normal shock)。

激波前后关系:

[equation]

[equation]

调整背压使激波位置移动。背压越高激波越靠近喉部,越低则越靠近出口。目标是将其布置在 [math] 区间。

---

模拟器的物理模型

本模拟器基于以下假设:

1. 1D 准一维(quasi-1D)流: 仅考虑截面积变化,忽略粘性/传热
2. 等熵流(激波除外): [math], [math] 守恒
3. 量热完全气体: math
4. 正激波: 应用 Rankine-Hugoniot 关系式
5. 喷管形状: Hermite 插值生成光滑的截面积分布

激波位置通过离散搜索满足出口压力条件的位置。激波前方为等熵超音速,后方为反映总压损失的等熵亚音速。

---

延伸阅读

- 可压缩多相流CFD入门 - 该模拟器的物理扩展到多相流时会出现哪些困难
- 从 Riemann 问题到 Godunov 型格式 - 数值捕获正激波的 Riemann solver
- FDM vs FEM vs FVM - 实际离散化此 1D 问题的三种方法

---
Read more: https://cfdblog.cc/zh/posts/mach-architect]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/mach-architect</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/mach-architect</guid>
      <pubDate>Wed, 11 Mar 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>CFD</category>
      <category>Compressible-Flow</category>
      <category>Interactive</category>
      <category>Isentropic</category>
      <category>Nozzle</category>
    </item>
    <item>
      <title><![CDATA[压缩性多相流 Rhie-Chow 插值法详解]]></title>
      <description><![CDATA[从同置网格的棋盘格问题到平衡力多相流，系统总结 Rhie-Chow 插值的数学本质及 OpenFOAM 实现。

[8 min read · 4,090 words]]]></description>
      <content:encoded><![CDATA[import { CheckerboardPressure } from '@/components/post-viz/rhie-chow-multiphase/CheckerboardPressure'

Rhie-Chow 插值：为什么需要它，以及在多相流中为什么棘手

Rhie-Chow 插值（动量加权插值，MWI）是在同置网格（collocated grid）上为了抑制棋盘格压力振荡而修正面（face）速度的核心技术。在单相流中这相对简单，但扩展到多相流时，压力、重力、表面张力以及非定常修正项的一致性处理变得至关重要。

本文涵盖了从 Rhie & Chow (1983) 的原型到 Bartholomew 等人 (2018) 的统一框架，以及 OpenFOAM 中 interFoam/compressibleInterFoam 的实现细节。

---

1. 从半离散动量方程推导面速度

所有 Rhie-Chow 变体公式的起点都是单元中心 [math] 点处的半离散（semi-discretized）动量方程：

[equation]

- [math]：对角项系数（包含时间导数、对流、扩散的贡献）
- [math]：相邻单元的贡献 + 显式源项

求解单元中心速度：

[equation]

问题：棋盘格振荡

如果直接通过简单线性插值将单元中心速度投影到面上，压力梯度只会连接 [math] 和 [math] 而跳过 [math]，从而导致奇偶解耦（棋盘格现象）。

Rhie-Chow 的解决方案

在面上重构动量方程本身，用紧致（compact）的面中心压力梯度代替宽模板的插值压力梯度：

[equation]

其中 [math] 是直接利用相邻单元值计算的面梯度，上划线表示单元中心值的线性插值。

压力修正项 [math] 起到了类似于 [math] 的低通滤波器作用，从而抑制棋盘格。

---

2. 核心论文的贡献

Rhie & Chow (1983)：原型

发表在 AIAA Journal 上的原文是专为稳态 SIMPLE 算法设计的：

[equation]

[math] 是去掉压力梯度的伪速度，[math]。它仅包含压力修正项，没有处理非定常项或松弛（relaxation）项。后来 Majumdar (1988) 指出了收敛解对松弛因子的依赖性，Choi (1999) 指出了非定常流中对时间步长的依赖性。

Jasak (1996)：OpenFOAM 的基石 - H/A 方法

在其伦敦帝国理工学院的博士论文中，系统化了非结构多面体网格的有限体积法。其特点是隐式实现 Rhie-Chow，而没有显式的修正项：

[equation]

HbyA = H/A 是去除了压力影响的速度预测值，压力方程推导为 [math]。Rhie-Chow 效应自然产生，因为拉普拉斯离散（面 snGrad）和速度修正的梯度（高斯定理）使用了不同的模板。

非定常修正通过 fvc::ddtCorr 处理，但并非完全一致，因此仍存在时间步长依赖性。

Cubero & Fueyo (2007)：紧致动量插值 (CMI)

提出了一个独立于时间步长和松弛因子的面速度公式。核心思想是分别且一致地插值动量方程的各个系数：

[equation]

- [math]：时间系数
- [math]：松弛系数
- [math]：空间系数

收敛时，[math] 且 [math]，因此非定常/松弛修正项会自动消失。这保证了稳态解与 [math] 及松弛因子…

---
Read more: https://cfdblog.cc/zh/posts/rhie-chow-multiphase]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/rhie-chow-multiphase</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/rhie-chow-multiphase</guid>
      <pubDate>Tue, 10 Mar 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>Multiphase</category>
      <category>Rhie-Chow</category>
      <category>OpenFOAM</category>
      <category>Numerical-Methods</category>
    </item>
    <item>
      <title><![CDATA[FDM vs FEM vs FVM：三种离散化技术的本质区别]]></title>
      <description><![CDATA[比较有限差分法 (FDM)、有限要素法 (FEM) 和有限体积法 (FVM) 的数学起点、优缺点以及各自擅长的领域。

[5 min read · 2,595 words]]]></description>
      <content:encoded><![CDATA[import { StencilCompare } from '@/components/post-viz/fdm-fem-fvm/StencilCompare'

同一 PDE，三条路径

要用计算机求解偏微分方程 (PDE)，必须对连续空间进行 离散化 (discretization)。即便对于同一个方程，根据离散化哲学的不同，也会演变为完全不同的数值技术。

我们以简单的一维平流-扩散方程为例：

[equation]

让我们看看 FDM、FEM 和 FVM 分别如何处理这一个方程。

---

1. 有限差分法 (Finite Difference Method, FDM)

核心思想

> 将微分直接近似为 差分 (difference)。

这是最直观的方法。通过对网格点 (node) 处的函数值进行泰勒级数展开来近似导数。

数学起点：泰勒展开

点 [math] 处的泰勒展开：

[equation]

由此导出差分近似：

前向差分 (Forward):
[equation]

中心差分 (Central):
[equation]

二阶导数:
[equation]

应用于平流-扩散方程

使用中心差分：

[equation]

这变成了关于网格点未知数 [math] 的联立常微分方程 (ODE) 系统。

优缺点

优点：
- 概念简单，实现容易
- 在结构化网格 (structured grid) 中非常高效
- 易于实现高阶精度 (紧致格式、类谱格式)
- 正交网格下矩阵结构清晰 (带状矩阵)

缺点：
- 难以应用于非结构化网格 (unstructured grid) —— 这是致命弱点
- 对于复杂几何形状的网格生成非常困难
- 不会自动满足守恒定律

代表性应用领域

- DNS/LES (基于正交网格的湍流模拟)
- 气象/海洋模型 (结构化网格)
- 地震波传播模拟
- 基于紧致格式的高精度计算

---

2. 有限要素法 (Finite Element Method, FEM)

核心思想

> 将解近似为 基函数 (basis function) 的线性组合，
> 并最小化 加权残差 (weighted residual)。

FEM 不直接求解微分方程。相反，它将其转换为称为 弱形式 (weak formulation) 的积分形式。

数学起点：弱形式 (Weak Form)

在原始 PDE (强形式，strong form) 上乘以测试函数 [math] 并积分：

[equation]

对扩散项应用分部积分 (integration by parts)：

[equation]

这就是 弱形式。请注意核心变化：

- 原本需要二阶导数，分部积分后 仅需一阶导数
- 放宽了对解的连续性要求 ([math])
- 边界条件自然地包含在内 (Neumann BC = 右侧项)

伽辽金近似 (Galerkin Approximation)

将解表示为基函数 [math] 的线性组合：

[equation]

在伽辽金方法中，测试函数和基函数取自同一空间 ([math])：

[equation]

矩阵形式：

[equation]

- [math]: 质量矩阵 (mass matrix)
- [math]: 刚度矩阵 (stiffness matrix)
- [math]: 边界/源项向量

基函数的选择

最常用的是基于 拉格朗日多项式 (Lagrange polynomial) 的…

---
Read more: https://cfdblog.cc/zh/posts/fdm-fem-fvm]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/fdm-fem-fvm</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/fdm-fem-fvm</guid>
      <pubDate>Mon, 09 Mar 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>CFD</category>
      <category>FDM</category>
      <category>FEM</category>
      <category>FVM</category>
      <category>数值方法</category>
    </item>
    <item>
      <title><![CDATA[Numerical Dungeon: 用游戏学数值方法]]></title>
      <description><![CDATA[从CFL条件到可压缩多相流,通关5个关卡掌握数值方法的核心概念。

[1 min read · 496 words]]]></description>
      <content:encoded><![CDATA[Numerical Dungeon

只看书学数值方法很枯燥。
通过通关5个关卡亲身掌握核心概念。

规则

- HP 3 格 - 答错扣 1 HP。HP 归零即游戏结束!
- XP - 每次答对获得 XP。越往后奖励越大。
- 难度 - 第 12 关基础,34 关核心理论,第 5 关终极 Boss。

每关先阅读概念讲解,然后回答测验题。
答错也会提供详细解析,把它当作学习机会。

---

---

各关卡深入学习

通关之后,可以深入学习各个主题:

第 1 关: CFL 条件
CFL 条件与 domain of dependence(依赖域)概念直接相关。
数值信息的传播速度必须快于物理信息的传播速度。
隐式(implicit)格式没有 CFL 限制,但需要付出求解非线性系统的代价。

第 2 关: 数值扩散
减少数值扩散需要高阶格式,但
根据 Godunov 定理需要非线性限制器。
常用限制器: minmod, van Leer, superbee, MC limiter。

第 3 关: Godunov 定理
该定理推动了 TVD(Total Variation Diminishing)、ENO、WENO 等
现代数值方法的发展。
核心是"非线性是高阶 + 稳定的关键"。

第 4 关: Riemann 问题
Sod、Lax、Shu-Osher 等标准测试问题可以验证 Riemann solver。
请参考本博客的从 Riemann 问题到 Godunov 型格式。

第 5 关: 多相流压力振荡
Abgrall 条件是多相流数值方法的起点。
请在5 方程模型实现指南中查看实际代码。

---
Read more: https://cfdblog.cc/zh/posts/numerical-dungeon]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/numerical-dungeon</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/numerical-dungeon</guid>
      <pubDate>Sun, 08 Mar 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>CFD</category>
      <category>Numerical-Methods</category>
      <category>Interactive</category>
      <category>Education</category>
    </item>
    <item>
      <title><![CDATA[5-Equation Model 实现指南：用 Python 编写多相流求解器]]></title>
      <description><![CDATA[使用 Python 手动实现 5-equation diffuse interface model，并模拟一维冲击波-气泡相互作用问题。

[1 min read · 650 words]]]></description>
      <content:encoded><![CDATA[import { VolumeFractionAdvect } from '@/components/post-viz/five-equation-model/VolumeFractionAdvect'

手动实现 5-Equation Model

仅仅靠理论是不够的。
在本文中，我们将使用 Python 手动实现一维 5-equation diffuse interface model，
并模拟冲击波穿透气泡的问题。

控制方程整理

一维 5-equation model 的守恒变量和通量：

[equation]

第 5 个方程 ([math]) 是非守恒型的，因此需要单独处理：

[equation]

状态方程：Stiffened Gas EOS

两种流体都使用 stiffened gas EOS：

[equation]

使用混合规则 (mixture rule) 计算总压：

[equation]

Python 实现

初始设置与 EOS

[code block]

HLLC 通量计算

[code block]

时间积分 (一阶)

[code block]

初始条件：冲击波-气泡

python
初始条件：冲击波撞击水中的气泡
U = np.zeros((4, N))
alpha1 = np.zeros(N)

for i in range(N):
    if x[i]

---
Read more: https://cfdblog.cc/zh/posts/five-equation-model]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/five-equation-model</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/five-equation-model</guid>
      <pubDate>Sat, 07 Mar 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>Multiphase</category>
      <category>Diffuse-Interface</category>
      <category>Python</category>
      <category>Implementation</category>
    </item>
    <item>
      <title><![CDATA[界面捕捉技术对比：VOF vs Level Set vs Diffuse Interface]]></title>
      <description><![CDATA[对比压缩性多相流中捕捉界面的三种代表性技术的原理、优缺点及应用案例。

[3 min read · 1,324 words]]]></description>
      <content:encoded><![CDATA[import { VOFvsLevelSet } from '@/components/post-viz/interface-capturing/VOFvsLevelSet'

如何处理界面

在压缩性多相流模拟中，最基本的问题之一是
“如何在数值上表示两种流体之间的界面 (interface)”。

主要存在三类方法：

1. Volume of Fluid (VOF)
2. Level Set
3. Diffuse Interface (扩散界面)

1. Volume of Fluid (VOF)

原理

追踪每个网格中特定流体所占的体积分数 (volume fraction) [math]。

[equation]

如果 [math]，表示该网格充满流体 A；
如果 [math]，表示充满流体 B；如果 [math]：流体 A
- $\phi

---
Read more: https://cfdblog.cc/zh/posts/interface-capturing]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/interface-capturing</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/interface-capturing</guid>
      <pubDate>Fri, 06 Mar 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>Multiphase</category>
      <category>VOF</category>
      <category>Level-Set</category>
      <category>Diffuse-Interface</category>
    </item>
    <item>
      <title><![CDATA[从 Riemann 问题到 Godunov 格式：数值通量的核心]]></title>
      <description><![CDATA[深入探讨 CFD 的核心——Riemann 问题，并了解 Exact/Approximate Riemann Solver 如何决定数值通量。

[2 min read · 1,034 words]]]></description>
      <content:encoded><![CDATA[import { RiemannFan } from '@/components/post-viz/riemann-solvers/RiemannFan'

Riemann 问题：CFD 的心脏

在有限体积法 (Finite Volume Method) 中，网格边界处数值通量 (numerical flux)的计算方式直接决定了解的准确性和稳定性。而决定数值通量的关键正是 Riemann 问题。

什么是 Riemann 问题？

Riemann 问题是一个初值问题，其初始条件由一个不连续面两侧的两个不同常数状态组成：

[equation]

对于一维 Euler 方程，该问题的解析解由三个波 (wave) 组成：

1. 左行波 (稀疏波 rarefaction 或 冲击波 shock)
2. 接触不连续 (contact discontinuity)
3. 右行波 (稀疏波 rarefaction 或 冲击波 shock)

Godunov 的思想 (1959)

Godunov 的核心见解简单而强大：

> 为了获得网格边界处的通量，可以将相邻两个网格的平均值作为左右状态，然后求解 Riemann 问题。

有限体积法的更新公式：

[equation]

这里的 [math] 正是根据 Riemann 问题的解确定的数值通量。

Exact Riemann Solver (精确解法)

精确 Riemann 求解器使用 Newton-Raphson 迭代法求解中间区域 (star region) 的压力 [math]。根据波的类型（冲击波/稀疏波）应用 Rankine-Hugoniot 关系式或等熵关系式。

冲击波 (Shock wave) 关系式 ([math], [math] 或 [math]):

[equation]

其中 [math]，[math]。

稀疏波 (Rarefaction wave) 关系式 ([math]):

[equation]

[math] 满足以下条件：

[equation]

Approximate Riemann Solver (近似解法)：为什么需要它？

由于精确求解器需要迭代计算，因此成本昂贵。在实际的 CFD 代码中，大多使用近似 Riemann 求解器 (approximate Riemann solver)。

Roe Solver (1981)

Roe 将非线性 Riemann 问题线性化 (linearization)，转化为关于矩阵 [math] 的线性 Riemann 问题：

[equation]

使用 Roe 平均 (Roe average) 构建 [math]：

[equation]

优点：能精确捕捉接触不连续。缺点：可能违反熵条件（需要熵修正 entropy fix）。

HLLC Solver (Toro, 1994)

HLLC 是对 HLL 求解器的改进，它恢复了接触不连续 (Contact)。它估计三个波速 (wave speed) [math], [math] 和 [math]：

$$
\hat{\mathbf{F}}{i+1/2} = \begin{cases}
\mathbf{F}L & \text{if } SL > 0 \\
\mathbf{F}^L & \text{if } SL \leq 0

---
Read more: https://cfdblog.cc/zh/posts/riemann-solvers]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/riemann-solvers</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/riemann-solvers</guid>
      <pubDate>Thu, 05 Mar 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>Riemann-Solver</category>
      <category>Godunov</category>
      <category>Numerical-Methods</category>
    </item>
    <item>
      <title><![CDATA[可压缩多相流CFD入门:为什么难,为什么重要]]></title>
      <description><![CDATA[整理可压缩多相流数值方法与单相流的本质区别,以及为何该领域至今仍是活跃的研究课题。

[2 min read · 808 words]]]></description>
      <content:encoded><![CDATA[import { SpeedOfSoundMix } from '@/components/post-viz/compressible-multiphase-intro/SpeedOfSoundMix'

什么是可压缩多相流?

在流体力学中,多相流(multiphase flow)指两个或更多相(phase)共存的流动。
水与空气、燃料液滴与高温气体、水下爆炸中的气泡等都是典型例子。

加上可压缩性(compressibility),问题就急剧复杂化。
各相拥有不同的状态方程(EOS),并以界面(interface)为分界
产生冲击波(shock wave),发生反射、透射、折射。

与单相可压缩流的区别

单相 Euler 方程如下:

[equation]

其中守恒变量 [math],
单一 EOS(例如理想气体 [math])即可闭合系统。

多相流中界面两侧 EOS 不同。
设气相区域使用 [math] 的理想气体,
液相区域使用 stiffened gas EOS:

[equation]

数值上的麻烦出现在界面附近两种 EOS 混合(mixing)时。
基于守恒变量直接平均会产生非物理的压力振荡(pressure oscillation)。

为什么难:三大核心难题

1. 界面处的压力振荡

最著名的问题。1994 年 Abgrall 指出后,
解决该问题成为多相流数值方法的起点。

> "可压缩多相流数值方法的历史,就是与压力振荡斗争的历史。"

普通的守恒型有限体积法,在界面处由于
[math] 取中间值会产生 spurious oscillation。

2. 状态方程的多样性

实际问题中仅靠理想气体不够。
水使用 Tait EOS 或 stiffened gas EOS,
高压状态使用 Jones-Wilkins-Lee (JWL) EOS,
反应性流动需要与化学反应耦合的 EOS。

需要对每种 EOS 推广 Riemann solver,实现复杂度大幅上升。

3. 界面追踪 vs 界面捕捉

如何处理界面大致分两种方法:

| 方法 | 实现 | 优点 | 缺点 |
|--------|------|------|------|
| Sharp interface | Ghost Fluid, Front Tracking | 界面清晰 | 相变难处理 |
| Diffuse interface | 5 方程、6 方程模型 | 自然处理相变 | 界面涂抹 |

为什么重要

可压缩多相流仿真在多个工程领域处于核心地位:

- 水下爆炸(UNDEX): 舰艇生存性评估
- 超音速燃烧: 冲压发动机内部燃料喷射/混合
- 医疗领域: 冲击波碎石(lithotripsy)中的气泡行为
- 航天推进: 低温推进剂的晃动(sloshing)

下篇预告

下一篇介绍该领域的核心工具:Riemann 问题与 Godunov 型格式。
首先理解单相 Euler 方程的 Riemann 问题,
再看它如何扩展到多相流。

将探针滑到 α≈0.5 附近，Wood 声速会降到单相的 1/100。

---
Read more: https://cfdblog.cc/zh/posts/compressible-multiphase-intro]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/compressible-multiphase-intro</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/compressible-multiphase-intro</guid>
      <pubDate>Wed, 04 Mar 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>CFD</category>
      <category>Multiphase</category>
      <category>Compressible-Flow</category>
      <category>Introduction</category>
    </item>
    <item>
      <title><![CDATA[[非公开] 撰写中的文章]]></title>
      <description><![CDATA[本文不会显示在主列表中,只能通过密码预览。

[1 min read · 24 words]]]></description>
      <content:encoded><![CDATA[私密文章

此内容只有输入管理员密码后才能查看。

[equation]

---
Read more: https://cfdblog.cc/zh/posts/draft-post]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/draft-post</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/draft-post</guid>
      <pubDate>Wed, 04 Mar 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>Draft</category>
      <category>Test</category>
    </item>
    <item>
      <title><![CDATA[用 Contentlayer 和 LaTeX 搭建博客]]></title>
      <description><![CDATA[使用 Next.js 16 与 Contentlayer 搭建技术博客的指南

[1 min read · 46 words]]]></description>
      <content:encoded><![CDATA[你好!

本博客使用 Next.js 和 Contentlayer 搭建。

数学公式测试 (LaTeX)

行内公式: [math]

块级公式:
[equation]

代码测试

[code block]

---
Read more: https://cfdblog.cc/zh/posts/hello-blog]]></content:encoded>
      <link>https://cfdblog.cc/zh/posts/hello-blog</link>
      <guid isPermaLink="true">https://cfdblog.cc/zh/posts/hello-blog</guid>
      <pubDate>Tue, 03 Mar 2026 00:00:00 GMT</pubDate>
      <author>noreply@cfdblog.cc (Younglin)</author>
      <category>Next.js</category>
      <category>Contentlayer</category>
      <category>MDX</category>
      <category>LaTeX</category>
    </item>
  </channel>
</rss>