一直很好奇WRF到底如何通過netcdf庫讀取netcdf文件,正巧有個機會,試了下fortran讀取nc文件,總結一下。
netcdf庫
Fortran讀取nc文件需要依賴netcdf外部庫。安裝該庫以后,會有專門寫給ffortran函數聲明的頭文件:netcdf.inc,使用該文件后,可以使用該文件里的函數。
通常,該頭文件在安裝的netcdf庫路徑的/include/下。
使用netcdf
在Fortran中,如果你的netcdf庫直接安裝在了fortran的路徑下,你可以直接:
use netcdf.mod
調用netcdf庫。
或者,你可以:
include 'netcdf.inc'
使用頭文件中聲明的函數。
需要注意的是,在一些大型服務器上,用戶并不具備root權限,因此,有時我們需要在編譯時告知fortran相應頭文件的位置,如:
gfortran read.f90 -I/usr/bin/netcdf/include
實例
首先查看一下nc文件基本信息:
獲取nc文件的變量與維度信息后,就可以開始讀取了。
program ReadNCinclude “netcdf.inc”IMPLICIT NONE! input file statusinteger:: ncid,status character (100) FileNameinteger, parameter :: x=1701,y=801,z=50,t=1integer,parameter::ki=selected_real_kind(8)real(ki),dimension(t,z,y,x):: zu !variables id integer::varid1FileName="nest_1_20100101000000.nc"write(*,*)trim(FileName)!open file status=nf_open(trim(FileName),nf_nowrite,ncid) !打開netcdf文件,獲取文件的ID號(ncid)if (status .ne. 0) thenprint*,"open failure!"stopend ifstatus=nf_inq_varid(ncid,'zu',varid1) status=nf_get_var(ncid,varid1,zu)write(*,*) zustatus=nf_close(ncid)
end program ReadNC
隨后編譯:
gfortran readnc.f90 -I /public/netcdf4/include/ -o readnc.exe -L/public/netcdf4/lib/ -lnetcdff -lnetcdf
得到real.exe,再運行生成的./real.exe即可。
WRF中的外部文件讀取
在WRF中,文件的讀取主要通過external文件夾中的函數。
并在frame/module_io.F文件中,同樣,在external//io_netcdf/下,存在著用來測試文件讀寫的代碼testWRFread.f90和testWRFwrite.f90。代碼較為簡潔,可用于查看學習。
program testread_johnuse wrf_dataimplicit none
#include "wrf_status_codes.h"
#include <netcdf.inc>character (80) FileNameinteger Commcharacter (80) SysDepInfointeger :: DataHandleinteger Statusinteger NCIDreal data(200)integer idata(200)real*8 ddata(200)logical ldata(200)character (80) cdatainteger OutCountinteger i,j,kinteger, parameter :: pad = 3integer, parameter :: jds=1 , jde=6 , &ids=1 , ide=9 , &kds=1 , kde=5integer, parameter :: jms=jds-pad , jme=jde+pad , &ims=ids-pad , ime=ide+pad , &kms=kds , kme=kdeinteger, parameter :: jps=jds , jpe=jde , &ips=ids , ipe=ide , &kps=kds , kpe=kdereal u( ims:ime , kms:kme , jms:jme )real v( ims:ime , kms:kme , jms:jme )real rho( ims:ime , kms:kme , jms:jme )real u2( ims:ime , jms:jme )real u1( ims:ime )integer int( ims:ime , kms:kme , jms:jme )real*8 r8 ( ims:ime , kms:kme , jms:jme )
……