一直很好奇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 ReadNC
include “netcdf.inc”
IMPLICIT NONE
! input file status
integer:: ncid,status
character (100) FileName
integer, parameter :: x=1701,y=801,z=50,t=1
integer,parameter::ki=selected_real_kind(8)
real(ki),dimension(t,z,y,x):: zu
!variables id
integer::varid1
FileName="nest_1_20100101000000.nc"
write(*,*)trim(FileName)
!open file
status=nf_open(trim(FileName),nf_nowrite,ncid) !打开netcdf文件,获取文件的ID号(ncid)
if (status .ne. 0) then
print*,"open failure!"
stop
end if
status=nf_inq_varid(ncid,'zu',varid1)
status=nf_get_var(ncid,varid1,zu)
write(*,*) zu
status=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_john
use wrf_data
implicit none
#include "wrf_status_codes.h"
#include <netcdf.inc>
character (80) FileName
integer Comm
character (80) SysDepInfo
integer :: DataHandle
integer Status
integer NCID
real data(200)
integer idata(200)
real*8 ddata(200)
logical ldata(200)
character (80) cdata
integer OutCount
integer i,j,k
integer, parameter :: pad = 3
integer, parameter :: jds=1 , jde=6 , &
ids=1 , ide=9 , &
kds=1 , kde=5
integer, parameter :: jms=jds-pad , jme=jde+pad , &
ims=ids-pad , ime=ide+pad , &
kms=kds , kme=kde
integer, parameter :: jps=jds , jpe=jde , &
ips=ids , ipe=ide , &
kps=kds , kpe=kde
real 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 )
……