CAMx模擬結果之壓縮_nc檔版本
Table of contents
背景
- nc版本對長時間的模擬結果已經產生較佳的壓縮效果,如果還需要挑選物質成分、整合成PM及VOC,則需要進一步計算。
- CAMx並沒有計算顆粒物的粒徑分布,因此需要假設一組合理的分布,才能進行計算。
- PM及VOC與所選取的反應機制有關,此處以cb6r4為例。
shkNC.py程式之執行
- 引數:nc 檔名稱
- 程式會在工作目錄製作新的模版
- 需要腳本mk_tmpV.cs
- template.nc會被覆蓋
- 結果檔:nc 檔名稱+”S”
程式說明
時間標籤之處理
- mk_tmpV.cs將原檔案的時間及物質維度予以縮減,以利變數刪除、更名之作業。然前者還需再延長,以符合原來檔案。
- 延長過程必須逐步一個個時間增加
#enlarge the timeframes
nt,nlay,nrow,ncol=nc0.variables[v4[0]].shape
var=np.array(nc0.variables['TFLAG'][:,0,:])
for t in range(nt):
nc1.variables['TFLAG'][t,0,:]=var[t,:]
var3=np.zeros(shape=nc1.variables['TFLAG'].shape)
var3[:,:,:]=var[:,None,:]
nc1.variables['TFLAG'][:]=var3[:]
個別物質之轉載
- 此處並未改變單位,直接由輸入檔轉寫。
- 物質項目名稱由template.nc彈性定義,但後3項是新項目,留待後續處理。
lis=list(filter(lambda x:nc1.variables[x].ndim==4, [i for i in nc1.variables]))
for sp in lis:
if sp in ['NMHC','PM10','PM25']:continue
nc1.variables[sp][:]=nc0.variables[sp][:]
VOC之整併
- 沒有轉換單位
- 碳數:來自手冊中所列之物質碳數表
- 避免使用nc檔作為疊代累加的容器,那會造成IO時間耗費。
#definition of NMHC species in shk
sVOCs=' AACD ACET ALD2 ALDX BENZ CRES ETH ETHA ETHY ETOH \
FACD FORM GLYD INTR IOLE ISOP ISP ISPD KET MEOH \
MEPX MGLY NTR OLE OPEN PACD PAN PAR PANX PRPA \
TOL TOLA TERP TRP XYL XYLA'.split()
num_C=[ 0., 0., 2., 0., 6., 0., 4., 0., 0., 0., \
0., 1., 0., 0., 2., 5., 5., 0., 3., 0., \
0., 0., 0., 2., 0., 0., 3., 0.5, 0., 0., \
7., 0., 10., 0., 8., 0.]
v2c={i:j for i,j in zip(sVOCs,num_C) if i in v4}
vocs=np.zeros(shape=(nt,nlay,nrow,ncol))
for sp in v2c:
vocs+=nc0.variables[sp][:]*v2c[sp]
nc1.variables['NMHC'][:]=vocs[:]
PM之整併
- PM2.5在各成分中的比例,來自文獻經驗值
part='PNO3 PSO4 PNH4 POA SOA1 SOA2 SOA3 SOA4 SOPA SOPB PEC FPRM FCRS CPRM CCRS NA PCL PH2O'.split()
fpm2_5=[0.58,0.85,0.774]+[1.]*10+[0.,0]+[0.312]*2+[0]
sp_f={i:j for i,j in zip(part,fpm2_5) if i in v4}
for s in 'pm2_5,pm10'.split(','):
exec(s+'=np.zeros(shape=(nt,nlay,nrow,ncol))')
for sp in sp_f:
pm2_5+=nc0.variables[sp][:]*sp_f[sp]
pm10 +=nc0.variables[sp][:]
nc1.variables['PM10'][:]=pm10[:]
nc1.variables['PM25'][:]=pm2_5[:]
nc1.close()
模板之處理(mk_tmpV.cs)
需求及必要性
- 新模板的水平網格系統及全域屬性都必須與要處理的nc檔相同
- 模板的物質變數必須保持彈性,因為不見得所有項目都會自CAMx程式輸出。
- 用裁剪或新增都太慢、且容易出錯,由原始檔案修剪變數項最快。
基本定義
- 基本上會輸出7個目標物質(
$lis
)、前4項為模式結果直接轉錄、後3項為合併後輸出,為新的物質項目。 $blk
為特定格數之空格,VAR-LIST每個物質名稱有16碼,還原時需加回去。$new
為不含空格的物質名稱。因cut
時會消去空格,所以需要前述對應之空格變數序列($blk
)。$var
為$nc
檔所有變數名稱(AR-LIST)。
lis='CO NO2 O3 SO2 NMHC PM10 PM25 '
blk=( " " " " " " " " " " " " " " )
new=()
for i in {0..6};do ii=$(( $i + 1 ));new=( ${new[@]} $(echo ${lis}|cut -d' ' -f$ii ));done
nc=$1
var=$(ncdump -h $nc|grep VAR-LIST|head -n1)
$nc
檔的變數個數
# make sure the number of species of incoming nc file is right
nvar1=$(ncdump -h $nc|grep NVARS|head -n1|awk '{print $3}')
var2=$(echo $var|sed 's/ /_/g')
var3=$(echo $var2|sed 's/_//g')
nvar2=$(( ${#var2} - ${#var3} - 3 ))
if [[ $nvar1 -ne $nvar2 ]];then echo $nvar1 -ne $nvar2;exit;fi
確認變數是否存在$nc
檔內
- 如果前4項變數存在
$nc
檔內,$ipas
為0、會將變數留在模板內,$ipas
若為1,則會跳過。 - 原來的
$lis
變成$lis_new
#check existence of species
a=()
for ((i=1;i<=$nvar1;i+=1));do ii=$(( $i + 2 ));vv=$(echo $var|cut -d' ' -f$ii);vv=${vv/\"};a=( ${a[@]} $vv);done
ipas=();lis_new='';nvar=7
for isp in {0..3};do
ipas_isp=1
for ((i=0;i<$nvar1;i+=1));do if [[ ${a[$i]} == ${new[$isp]} ]];then ipas_isp=0;fi;done
ipas=( ${ipas[@]} $ipas_isp )
if [[ ipas_isp -eq 0 ]];then
lis_new=${lis_new}${new[$isp]}${blk[$isp]}
else
nvar=$(( $nvar - 1 ))
fi
done
for isp in {4..6};do lis_new=${lis_new}${new[$isp]}${blk[$isp]};ipas=( ${ipas[@]} 0 );done
切出前$nvar
項物質當成模板
- 確認
$nc
檔內有多少物質可以輸出,就(才)可以從該檔切出同數量的變數作為模板。 - 因為要做
ncrename
,所以變數名稱要記清楚($v
)。 ncks
除了切時間項、也切VAR維度,這樣TFLAG的維度才會正確。ncatted
修正VAR-LIST及NVARS等2個屬性
#store the first $nvar specises for ncrenaming
v=()
for ((i=1;i<=$nvar;i+=1));do ii=$(( $i + 2 )); vv=$(echo $var|cut -d' ' -f$ii);vv=${vv/\"};v=( ${v[@]} $vv);done
#streaming these specise for ncks command
vv='';nvm1=$(( $nvar - 1 ))
for ((i=0;i<$nvar;i+=1));do vv=$(echo ${vv},${v[i]});done
ncks -O -d TSTEP,0 -d VAR,0,$nvm1 -v TFLAG$vv $nc template.nc
ncatted -a VAR-LIST,global,o,c,"${lis_new}" template.nc
ncatted -a NVARS,global,o,i,$nvar template.nc
變數名稱更新
- 目標變數名稱
$new2
:由前述$lis_new
及${ipas[@]}
而來 - 找出新、舊檔變數名稱相同的交集(
${intr[@]}
)- 如果變數是交集內項目、(
$iskip=1
)就不必更名 - 如果不是,舊依序更名,並將long_name屬性改正確
- 更改過的變數,就放到交集中,這樣就不會重複更名。
- 如果變數是交集內項目、(
#rename the first $nvar specises
new2=();intr=();ii=1
for ((i=0;i<7;i+=1));do test ${ipas[$i]} -eq 1 && continue;new2=( ${new2[@]} $(echo ${lis_new}|cut -d' ' -f$ii ));ii=$(( $ii + 1 ));done
for ((i=0;i<$nvar;i+=1));do for ((j=0;j<$nvar;j+=1));do if [[ ${v[$j]} == ${new2[$i]} ]];then intr=( ${intr[@]} ${v[$j]} );continue;fi;done;done
nv=$(echo ${#v[@]})
ni=$(echo ${#intr[@]})
for ((i=0;i < $nv; i+=1));do
n=${new2[$i]}
iskip=0;for ((j=0;j < $ni; j+=1));do c=${intr[$j]}; test $c == $n && iskip=1;done; if [[ $iskip == 1 ]];then continue;fi
for ((k=0;k < $nv; k+=1));do
o=${v[$k]}
iskip=0;for ((j=0;j < $ni; j+=1));do c=${intr[$j]}; test $c == $o && iskip=1;done; if [[ $iskip == 1 ]];then continue;fi
break
done
ncrename -O -v ${o},${n} template.nc
ncatted -a long_name,${n},o,c,"${n}" template.nc
ni=$(( $ni + 1 ))
intr=( ${intr[@]} $o )
done
程式下載
Download: nc檔版本CAMx模擬結果之壓縮程式:shkNC.py
Download: 製作nc檔模版本之腳本:mk_tmpV.cs