JOVANA
Explore Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

馮諾伊曼分析與 CFL 條件

上一篇指南承諾穩定性是收斂裡較難的那一半——但你究竟要怎麼檢查它?馮諾伊曼分析用一個優雅的把戲回答:餵給你的格式一個純波,再問它會不會放大。著名的 CFL 條件就從這裡掉出來,那是一道速度上限,精準告訴顯式格式它最大被允許走多大的時間步。

穩定性需要一個檢驗,而不是一種感覺

上一篇指南留給我們一個清楚的分工:根據 Lax 等價定理,對於良置線性問題上的相容格式,收斂成立若且唯若格式穩定。相容性是簡單的那一半——你只要把模板做泰勒展開,確認 截斷誤差 隨網格縮小而消失即可。穩定性則是真正難的那一半:它問的是,每一步在每個網格點誕生的微小誤差,在你走越來越多步之後到底會保持有界、還是會像雪球般滾大。我們需要一個具體、機械化的檢驗。那個檢驗就是 馮諾伊曼穩定性分析

在任何公式之前,先講直覺。一個線性的更新規則,不過是一台機器:它吃進時間層 n 在網格上的那些數字,吐出層 n+1 的數字。因為它是線性的,疊在解上面的誤差會遵守和解完全相同的更新規則。所以真正的問題是:當這台機器一遍又一遍地作用時,誤差到底是被放大還是被衰減?如果我們能把任意誤差拆成簡單的小塊、看機器對每一小塊做了什麼、並發現沒有任何一塊會成長,那就大功告成了。傅立葉模態正是那些簡單的小塊。

餵給格式一個單一的波

把戲在於:拿一個純傅立葉模態去測試格式,剩下的交給線性。把點 j、時間層 n 的網格值寫成複數波 U_j^n = G^n e^{i k x_j},其中 k 是波數(每單位長度有幾個起伏),G 是一個未知的複數,叫做 放大因子。波的空間形狀 e^{i k x_j} 固定不變;唯一逐步改變的,是它被乘上 G。走一步後振幅變成 |G| 倍;走 n 步後變成 |G|^n 倍。所以這個模態的整個命運,就由一個數字 |G| 決定。

現在這個要求就一目了然了。如果哪怕只有一個波數 k 讓 |G| > 1,那個模態每一步都把自己乘得更大,走夠多步後就爆炸——這正是 數值不穩定,解膨脹成垃圾或 NaN。如果對「所有」k 都有 |G| <= 1,每個模態都保持有界,格式就穩定。所以 馮諾伊曼穩定性條件 很簡單:對網格能表示的每一個波數 k,都要 |G(k)| <= 1。(嚴格說我們允許 |G| <= 1 + C*dt,其中 C 為常數,這在有限時間內仍能讓成長保持有界;對這裡的純常係數格式,|G| <= 1 就是乾淨的說法。)

  1. 把試探模態 U_j^n = G^n e^{i k x_j} 代入差分格式,替換掉每個時間層、每個網格點上的每個 U。
  2. 消去每一項裡都出現的公因子 G^n e^{i k x_j};剩下的是一個關於 G、以 k 為參數的代數方程。
  3. 用恆等式 e^{i theta} + e^{-i theta} = 2 cos(theta) 把鄰居項收成餘弦;記帳會乾淨許多。
  4. 解出 G(k),再找出「最壞」的模態——讓 |G| 最大的那個波數——並要求連那個最壞的 |G| 都保持 <= 1。
  5. 存活下來的那個不等式就是你的穩定性條件:通常是對時間步 dt 相對於網格間距 dx 的一道上限。

一個算例:用 FTCS 解熱傳導

取熱傳導方程 u_t = alpha u_xx,以及第二篇指南裡的顯式 FTCS 格式:時間用前向差分、空間用中央二階差分。更新式是 U_j^{n+1} = U_j^n + r (U_{j+1}^n - 2 U_j^n + U_{j-1}^n),其中 r = alpha dt / dx^2 是那個掌控一切的唯一無因次數。代入試探模態、消去公因子,餘弦恆等式就把三個鄰居項變成 G 的一個整潔表達式。

FTCS for u_t = alpha u_xx,  with  r = alpha dt / dx^2 :

  U_j^{n+1} = U_j^n + r ( U_{j+1}^n - 2 U_j^n + U_{j-1}^n )

Insert  U_j^n = G^n e^{i k x_j} ,  let  theta = k dx ,  divide out  G^n e^{i k x_j} :

  G = 1 + r ( e^{i theta} - 2 + e^{-i theta} )
    = 1 + r ( 2 cos(theta) - 2 )
    = 1 - 4 r sin^2(theta/2)            # since 1 - cos = 2 sin^2(half)

Worst mode  theta = pi  (the +,-,+ sawtooth)  gives  G = 1 - 4 r .
Need  |G| <= 1  for ALL theta   ==>   -1 <= 1 - 4 r   ==>   r <= 1/2 .

Stability:   alpha dt / dx^2 <= 1/2  .
熱傳導方程 FTCS 的馮諾伊曼分析。這裡 G 是實數;最緊的約束來自最高頻的鋸齒模態(theta = pi),它逼出 r <= 1/2。

讀懂 r <= 1/2 到底在說什麼,因為它很殘酷。它說 alpha dt <= dx^2 / 2,所以時間步必須像 dx^2 那樣縮小。把網格間距減半、讓空間解析度加倍,你就必須走「四倍」多的時間步才能到達同一個終點時間。想要空間細 10 倍?付出 100 倍的時間步。這是顯式格式對拋物型問題的詛咒:空間上的細化會在時間上受到平方級的懲罰。這正是 隱式格式 BTCS 與 Crank-Nicolson 存在的具體理由——它們的馮諾伊曼分析對「每一個」r 都給出 |G| <= 1,因此無條件穩定,你選 dt 只為了精度、而不是為了活命。

CFL 條件:資訊不能跑得比網格快

對於波動型(雙曲型)問題,同一套機制會產生一個不同而著名的界。取對流方程 u_t + a u_x = 0,它單純把一個剖面以速度 a 向右搬運。最自然的顯式選擇 迎風格式,給出一個放大因子,其模在 Courant 數 C = |a| dt / dx 至多為 1 時恰好保持 <= 1。那個單一不等式 |a| dt / dx <= 1,就是 CFL 條件(以 Courant、Friedrichs、Lewy 三人命名,1928 年)。

代數背後有一幅美麗的物理圖像。真實解在某點只依賴它解析上的依賴域:對速度為 a 的對流,(x, t) 處的答案完全由上游 a*dt 距離處的那一點決定。而格式有它自己的 數值依賴域——真正餵進更新的那組網格點,每步只能伸出一格寬 dx。CFL 不過就是要求:數值依賴域必須「包含」真實的依賴域。如果在一個時間步內物理訊號跑得比一格還遠(C > 1),格式就是在用它從沒看過的資料去算答案——資訊跑贏了網格——而再聰明的加權也救不了它。

當 G 是複數:耗散與頻散

穩定性只問 G 的「大小」,|G| <= 1。但 G 是複數,所以它還有「相位」,而相位承載了故事的其餘部分。精確的對流模態應該完全保持振幅(波在行進時既不長大也不縮小),並把相位剛好平移到以速度 a 移動它所需的量。真實的格式在這兩件事上都會失準,而這兩種失準各有名字。當那些本該被保留的模態出現 |G| < 1 時,格式就在悄悄抽乾它們的振幅——那是 數值耗散,它表現為一個銳利的鋒面被抹糊成柔軟的模糊。

相位誤差也有自己的名字:數值頻散。如果不同波數以略為不同的數值速度行進——而它們本該全都以同一個速度 a 移動——那麼由許多模態組成的銳利脈衝就會彼此漂開,於是你看到虛假的波紋,通常拖在陡峭鋒面後方,像船尾的漣漪。迎風格式高度耗散(鋒面變糊但仍平滑);中央的 蛙跳格式 幾乎無耗散卻強烈頻散(鋒面保持銳利卻長出振盪的波紋)。天下少有白吃的午餐:抑制波紋你就抹糊鋒面;保住鋒面你就得冒波紋的險。

誠實地把這一切記牢。在週期性、常係數的模型上做馮諾伊曼分析,是該問的第一個問題,而拿到 |G| <= 1 沒有商量餘地——不穩定的格式產生的是字面意義上的垃圾。但通過穩定性檢驗「不」代表你的答案好:穩定的格式可以把一個乾淨的波耗散或頻散成一團糊,而且這一切都跑在 浮點運算 上,所以算出來的 G 本身也被捨入,一個剛好坐在 |G| = 1 上的臨界穩定格式,可能被捨入誤差推過邊界。值得信賴的判決來自收斂(下一級的人造解測試),而不是單靠穩定性。