從第三根支柱,到一台真的會預報的機器
上一篇主張:模擬是科學的第三根支柱,與理論、實驗並立。這一篇要把那個抽象的主張,落實到它在你日常生活裡現身的地方:天氣預報。計算流體力學,也就是 CFD,是一門把流動流體——空氣、水、血液、火焰、恆星熔融的內部——的方程式,化成電腦能在時間中往前推進的數字的藝術。而一個天氣模型,不過就是人類每天跑好幾次、規模最大、後果也最重的那一場 CFD 計算,跑在地球上某些最龐大的機器上。
讓人安心的部分在這裡:每一樣材料你都已經見過。那些方程式是定義在計算網格上的偏微分方程。它們由一個時間步進法在時間中往前推進,而它能用的穩定步長,被 CFL 條件圍住。空間的部分,最常由你在有限元素/有限體積那一級學過的有限體積法來處理。真正新的東西不是這套機器,而是規模、真實湍流的雜亂,以及這場計算如何被源源不絕的觀測資料持續修正。我們會一層一層、誠實地把這份預報搭建起來。
Navier-Stokes 方程,以及「銳利網格」這個謊言
CFD 的核心坐著 Navier-Stokes 方程:它沒什麼神祕的,就是牛頓定律「質量乘加速度等於力」,同時替每一小團流體寫出來而已。它說:一團流體會加速,是因為壓力差在推它、黏滯性(內部摩擦)在拖它、整體流動在帶著它走。那個「帶著走」的項——流體輸送著自己的動量——是非線性的,而正是這一個非線性,是所有困難的源頭:湍流、混沌,還有一道未解的 Clay 千禧年問題。要跑一場 Navier-Stokes 模擬,你把區域切成許多控制體積,追蹤每個格子裡的平均速度與壓力,並結算質量與動量跨過每一道共享面時的通量。
現在來第一段硬誠實。今天天氣模型的網格格子有數十公里寬;就算最精細的研究級計算,也無法解析一朵雷暴雲,更別說那些一路翻滾到毫米尺度、能量真正被黏滯性耗散掉的渦旋。真實的流動是湍流——在極大的尺度範圍內,漩渦套著漩渦的層層串接——而你負擔得起的網格,沒有一個能把它們全部抓住。靠直接解析每一個渦旋來解 Navier-Stokes(叫做 DNS),只有對極小的實驗室盒子才可行;它的成本大約隨雷諾數的三次方增長,而對大氣層而言,那是天文數字般遙不可及。所以每一場實用的 CFD 計算,都在對「發生在網格之下的運動」做一個刻意而無可避免的近似。
往前推進而不爆掉:CFL 以及顯式/隱式的抉擇
一旦空間被離散成格子,你手上就剩下一個在時間上的巨大常微分方程組——這正是 PDE 那一級的線方法。把它往前推進看似簡單,卻藏著定義真實 CFD 的那個陷阱:穩定性。如果你採用的顯式步長太大,方法就會在每一步放大微小的誤差,整場模擬會在幾次迭代之內發散成一堆無意義的東西。把安全步長圍住的條件就是 CFL 條件,而它的意義美妙地物理:在一個時間步裡,資訊不能被允許跑過超過一個格子。
CFL number C = a * dt / dx <= C_max (often ~1) a = fastest signal speed in the flow (e.g. sound speed) dt = time step dx = grid spacing refine the grid 2x -> dx halves -> dt must halve too so total work for a fixed forecast grows like (refine)^4 in 3D+time
那為什麼不乾脆永遠用很小的步長?因為剛性(stiffness),而在這裡,你先前見過的顯式對隱式抉擇,變成了一個生死攸關的工程決定。大氣裡帶著聲波與快速重力波,它們對明天的天氣在物理上幾乎無關緊要,但一個剛性的顯式方法,卻被那些快波要求的極小步長逼著用爬的。解方是把那快速、剛性的部分用隱式來處理——每一步解一個大型線性系統,像 Crank-Nicolson 風格的更新那樣——好讓時間步能跟著你真正在乎的慢速天氣走。隱式步每一步更貴,卻讓你能跨出大得多的步;現代預報模型採用巧妙的半隱式分裂,正是為了甩開那些無關緊要的快波套在 CFL 上的繩索。
預報其實是從哪裡開始的:資料同化
這是大多數人從來沒聽過的部分。一個天氣模型是個初值問題:給它「此刻大氣的確切狀態」,它就往前推。但我們並不知道此刻的狀態。觀測是零散、稀疏而帶雜訊的——這裡一個浮標、那裡一顆氣球、一筆只能間接感測溫度的衛星輻射值。把這些碎片縫成一個完整、物理上自洽的全球起始狀態,本身就是一整門科學,叫做資料同化,而現代預報大約一半的本事,其實正是從這裡來的。它是一個反問題:從間接、不完整的量測,推斷出隱藏的狀態。
那個優雅的訣竅,是把兩樣不完美的東西,融合成一樣比較好的東西。你有一份六小時前算出的短期預報(模型對「現在」的最佳猜測),以及一批新鮮的觀測;兩者各自帶著自己的不確定性。把它們各按你對其信任的程度加權,做出的最佳融合,正是你在學狀態估計時見過的卡爾曼濾波器背後的想法。各國作業中心跑著工業強度的版本(系集或變分,常是兩者的混合),處理上億個未知數,每隔幾小時就重複這個循環:往前預報、朝觀測微調、再預報。你在手機上讀到的那份預報,就是這個無盡之輪最新轉出的一圈。
混沌、系集,與一根誠實的誤差棒
就算有一個完美的模型加上一台完美的電腦,也無法預報一個月之後,而原因是本篇最深的一段誠實。大氣是混沌的:那個造就湍流的同一個非線性,也讓流動對自己的起始狀態極度敏感。初始條件裡一個微觀的誤差會指數增長,每隔幾天就翻倍,直到它淹沒整份預報——這就是 Lorenz 著名的「蝴蝶」。這不是一種你能靠工程手段消除的數值不穩定;它是真實方程式本身的一個性質。它劃下了一道大約兩週的硬性可預報界線,無論多少算力都推不過去。
成熟的回應,不是假裝混沌不存在,而是去量度它。各中心不跑單一一份預報,而是跑一個系集:從略微擾動過的初始狀態出發的數十份預報。當這些成員彼此靠得很近,代表大氣正處於可預測的心情,你可以信這份預報;當它們狂野地散開,代表未來真的不確定,而模型也照實這麼說。那個離散程度,就是你誠實的誤差棒——一份活生生的不確定性量化。這就是為什麼一份好的預報給的是「七成機率下雨」,而非一個虛假的承諾:那個百分比,字面上就是系集成員裡下了雨的那一部分比例。
它的規模,以及底下那道未解的問題
為什麼這需要地球上最大的機器?算一算成本。一個全球模型,在數億個格子裡攜帶著風、溫度、壓力與濕度,在數千個微小時間步上往前推進,而整件事必須在一小時內算完才有用——一份要花一整天才算出明天天氣的預報,毫無價值。所以這場計算靠區域分解被切到數十萬個處理器上——每個處理器負責地球的一塊,並在每一步透過訊息傳遞把邊界值和鄰居交換。朝著能解析單一風暴的公里級全球模型推進,是百萬兆級(exascale)計算的一面旗幟性的驅動力,而在那裡,瓶頸很少是純粹的算術;而是把資料在處理器之間、以及穿過記憶體階層搬得夠快。
而在最底層,躺著一個值得直白說出來、令人謙卑的事實。我們每一天都在用 Navier-Stokes 方程計算,並取得了驚人的實務成功——然而,沒有人證明過三維方程恆有一個光滑、行為良好的解。完全有可能,真實的方程會在有限時間內自發地形成一個奇異點,一個速度無窮大的點。它們究竟會不會,就是 Navier-Stokes 存在性與光滑性問題,七道 Clay 千禧年大獎難題之一,而它至今仍然懸而未決。我們在一個最深的數學地板都還沒釘牢的地基上,設計飛機、預報颶風——這生動地提醒我們:計算上的成功與完整的數學理解,並不是同一回事,也正好是通往下一篇「數值方法與機器學習之間雙向往來」的一座完美橋樑。