2015年3月25日

較小的模式輸出檔:addfile v.s. addfiles

無論使用 WRF 模式或其他大氣模式,通常使用者可以決定輸出檔中要包含哪些變數,輸出的頻率 (每小時一筆或每六小時一筆?),還有單一輸出檔要包含幾個時間點 (有時候是限制單一輸出檔的最大容量)。

舉例來說,假設一個模擬實驗的解析度、模擬範圍、輸出的變數全部加起來,每一個時間點的輸出需要 2GB 的儲存空間。如果研究一個溫帶氣旋的生命史,總共模擬了 7 天,每 3 小時輸出一筆資料,總共會有 56 筆 (個時間點) 的資料。此時有兩種選擇:
1. 將這 56 筆資料輸出成一個 .nc 檔,檔案中的變數維度是 var ( nT = 56 , nZ , nY , nX )。
2. 每 3 小時輸出成一個 .nc 檔,總共會有 56 個檔案,檔案中的變數是 var ( 1 , nZ , nY , nX )。

第一種方案,1 個輸出檔,檔案大小 112 GB;第二個方案,56 個輸出檔,每個檔案 2 GB。筆者個人習慣 (也建議大家) 選用方案二,每一個時間點輸出成獨立的檔案

檔案小有什麼好處?基本上沒什麼太大的差別啦其實。檔案小在搬移、傳檔、存取的時候比較簡單快速一些。但是,但是,但是如果選擇方案一的理由只是因為想省讀資料的麻煩,想一行指令把 var ( nT , nZ , nY , nX ) 整串資料讀出來,不想在一個一個小檔案裡面抓資料自己拼湊出時間序,請看接下來的介紹:addfiles。這個超級好用的函數方便到讓你找不到偷懶選方案一的藉口!

讀取檔案清單

假設選用方案一得到 1 個大檔案:wrfout_total,選用方案二的到 56 個小檔案:wrfout_00 ~ wrfout_55 ( WRF 的輸出檔沒有副檔名 .nc )。下面介紹如何讀取輸出檔裡面的變數:var ( 56 , nZ , nY , nX )。

第一個檔案直接讀就好
ncFile1 = addfile ( "wrfout_total"+".nc" , "r" )
VAR1 = ncFile1->var

處理第二種檔案,不需要自己一個一個去開 56 個檔案,利用 Linux 指令 "ls" 把 56 個檔案的檔案清單建立起來,並用 addfiles 一次讀取
FileList2 = systemfunc ( "ls wrfout_??" ) + ".nc"
print ( "" + FileList2 )
ncFile2 = addfiles ( FileList2 , "r" )
VAR2 = ncFile2[:]->var

addfiles 比 NCL101 中介紹的 addfile 函數多了一個 s,專門用來讀取一串檔案清單。比較特別的是在讀資料的時候要多加一個 [:] 在檔名後面。範例中讀出來的 VAR1 和 VAR2 會是同一個變數,維度都是 ( 56 , nZ , nY , nX )!

註:FileList 後面加的副檔名 ".nc" 只要 script 中有寫就可以了,不用真的去改輸出檔檔案的名稱。

系集模擬結果

所謂系集 (ensemble) 模擬,通常一個實驗重複跑數十次,所以即使選用方案一,每個實驗一個大輸出檔案,30 個系集模擬還是必須處理 30 個輸出檔。addfiles 也適用於這樣的情況,只是這個 FileList 不再是時間的集合,而是模擬編號的集合。換句話說,前面的用法是將 56 個 ( 1 , nZ , nY , nX ) 的東西拼成一個 ( 56 , nZ , nY , nX ),第 1 個維度是時間。而現在要做的,是要再創造一個新的維度,把 30 個 ( 1 , nZ , nY , nX ) 併成一個 ( 30 , 1 , nZ , nY , nX ),變成 5 個維度的變數,增加的第一個維度是實驗編號。

方法是
FileList3 = systemfunc ( "ls wrfout_ens??" ) + ".nc"
print ( "" + FileList3 )
ncFile3 = addfiles ( FileList3 , "r" )
ListSetType ( ncFile3 , "join" )
VAR3 = ncFile3[:]->var

Take Home Message

檔案小又多  >>  檔案少但大

沒有留言:

張貼留言