一直很好奇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 )
……