Link Search Menu Expand Document

CAMx模擬結果之壓縮_nc檔版本

Table of contents

背景

  • nc版本對長時間的模擬結果已經產生較佳的壓縮效果,如果還需要挑選物質成分、整合成PM及VOC,則需要進一步計算。
  • CAMx並沒有計算顆粒物的粒徑分布,因此需要假設一組合理的分布,才能進行計算。
  • PM及VOC與所選取的反應機制有關,此處以cb6r4為例。

shkNC.py程式之執行

  • 引數: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

程式下載