- 积分
- 2115
- 贡献
-
- 精华
- 在线时间
- 小时
- 注册时间
- 2011-8-19
- 最后登录
- 1970-1-1
|
登录后查看更多精彩内容~
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
!读取grads的ctl描述的数据,生成netcdf4格式
!编译方法: 请根据自己实际环境进行修改
!pgf90 -I/opt/local/netcdf/include -L/opt/local/netcdf/lib -lnetcdff nc4write3D.f90 -o nc4write3D.exe
!by wsd@cma.gov.cn
!nc4相关定义
use netcdf
parameter (NDIMS2=2,NDIMS3=3,maxitem=20)
integer iddimsize2(NDIMS2),iddimsize3(NDIMS3),chunks(NDIMS2),chunks3(NDIMS3),idnc,id_lat,id_lon,id_lev,iddim_lat,iddim_lon,idallvar(maxitem)
real, dimension(:), allocatable :: lat_array,lon_array,lev_array
integer start(NDIMS3), count(NDIMS3)
!数据相关的定义
integer ,iy0,ix0,iz0,ctlvarflag(maxitem)
real, dimension(:,:), allocatable :: realvar
real, dimension(:,:,:), allocatable :: realvar3d
real levels(1000)
character*20 chvarname(2,maxitem) !1:varname,2:unitname
character*180 cmd,filectl,nameofdat,nameout
numarg = iargc()
call getarg(0,cmd)
if(numarg<1)then ! .or. numarg /=2
write(*,'(a)')'Usage: '//trim(cmd)//' xxxx.ctl'
write(*,'(a)')' ie: '//trim(cmd)//' shelt.ctl'
write(*,'(a)')' ie: '//trim(cmd)//' latlon_shelt.ctl'
stop
endif
call getarg(1,filectl)
call readctl(filectl,nameofdat,nameout,ctlvarflag,ix0,iy0,iz0,startx,starty,stepx,stepy,nvar,chvarname,maxitem,undef,if3d,levels,1000)
ifgeog=1;if(abs(startx-starty-stepx+stepy)<0.01)ifgeog=0 !检测ctl是否有地理信息
!write(*,*)abs(startx-starty-stepx+stepy),'====',ifgeog
ALLOCATE(lon_array(ix0),lat_array(iy0),lev_array(iz0),realvar(ix0,iy0))
if(if3d==1)then
ALLOCATE(realvar3d(ix0,iy0,iz0))
!write(*,*)isz0,' levels:',levels(1:iz0)
endif
open(10,file=nameofdat,status='old',form='binary',err=999)
iret = nf90_create(trim(nameout)//'.nc', nf90_netcdf4, idnc) ! Create the file.
!设置各坐标变量
if(ifgeog==1)then!是经纬度格式,则设置地图经纬度相关信息
write(*,'(4i5,4f9.3,f10.1,i2)')ix0,iy0,iz0,nvar,startx,starty,stepx,stepy,undef,if3d
do i=1,ix0
lon_array(i)=startx+real(i-1)*stepx
enddo
do j=1,iy0
lat_array(j)=starty+real(j-1)*stepy
enddo
do j=1,iz0
lev_array(j)=levels(j)
enddo
!定义维数
iret = nf90_def_dim(idnc, 'latitude', iy0, iddim_lat);if (iret .ne. nf90_noerr) call handle_err(iret)
iret = nf90_def_dim(idnc, 'longitude', ix0, iddim_lon);if (iret .ne. nf90_noerr) call handle_err(iret)
iret = nf90_def_dim(idnc, 'level', iz0, iddim_lev);if (iret .ne. nf90_noerr) call handle_err(iret)
!定义经纬度变量
iret = nf90_def_var(idnc, 'latitude', NF90_REAL, iddim_lat,id_lat);if (iret .ne. nf90_noerr) call handle_err(iret)
iret = nf90_def_var(idnc, 'longitude', NF90_REAL, iddim_lon,id_lon);if (iret .ne. nf90_noerr) call handle_err(iret)
iret = nf90_def_var(idnc, 'level', NF90_REAL, iddim_lev,id_lev);if (iret .ne. nf90_noerr) call handle_err(iret)
!写经纬度属性
iret = nf90_put_att(idnc, id_lat, 'units', 'degrees_north');if (iret .ne. nf90_noerr) call handle_err(iret)
iret = nf90_put_att(idnc, id_lon, 'units', 'degrees_east');if (iret .ne. nf90_noerr) call handle_err(iret)
if(if3d==1)then
iret = nf90_put_att(idnc, id_lev, 'units', 'm'); if (iret .ne. nf90_noerr) call handle_err(iret)
endif
else !无地理属性,直接写维数
write(*,'(4i5,f10.1)')ix0,iy0,iz0,nvar,undef
iret = nf90_def_dim(idnc, 'x', ix0, iddim_lon)
iret = nf90_def_dim(idnc, 'y', iy0, iddim_lat)
iret = nf90_def_dim(idnc, 'z', iz0, iddim_lev)
endif
iddimsize2 = (/ iddim_lon, iddim_lat /)
iddimsize3 = (/ iddim_lon, iddim_lat, iddim_lev /)
chunks = (/ix0,iy0/)
chunks3 = (/ix0,iy0,1/) !对于大的3D数组,只能这样设置,较小的可以将Z方向也设上
levelofdeflate=1 !压缩强度,1已经达到足够的压缩比了,9则耗费太多的时间
!设置各要素变量
do j=1,nvar !依次定义各变量
write(*,'(a,i2,2x,a)')'defing ',j,trim(chvarname(1,j))//' '//trim(chvarname(2,j))
if(ctlvarflag(j)==2)then
iret = nf90_def_var(idnc, trim(chvarname(1,j)),NF90_REAL,iddimsize2,idallvar(j),chunksizes=chunks)!,shuffle=.TRUE.,deflate_level=deflate_level)
elseif(ctlvarflag(j)==3)then
iret = nf90_def_var(idnc, trim(chvarname(1,j)),NF90_REAL,iddimsize3,idallvar(j),chunksizes=chunks3)!,shuffle=.TRUE.,deflate_level=deflate_level)
endif
iret = nf90_def_var_deflate(idnc, idallvar(j), 1, 1, levelofdeflate)
iret = nf90_put_att(idnc, idallvar(j), 'units',trim(chvarname(2,j)));if (iret .ne. nf90_noerr) call handle_err(iret) ! len_trim(chvarname(1,j)),
iret = nf90_put_att(idnc, idallvar(j), 'missing_value', undef)
enddo
iret = nf90_enddef(idnc);if (iret .ne. nf90_noerr) call handle_err(retval) !完成定义工作
!写入各数据
if(ifgeog==1)then!是经纬度格式,非经纬度的3D数组则不用设置
iret = nf90_put_var(idnc, id_lat, lat_array)
iret = nf90_put_var(idnc, id_lon, lon_array)
if(if3d==1)iret = nf90_put_var(idnc, id_lev, lev_array)
endif
count=(/ix0,iy0,iz0/);start=(/1,1,1/) !3D和4D数据写入必须要这些
do j=1,nvar
if(ctlvarflag(j)==2)then
write(*,*)'writing 2D',j
read(10)realvar
iret = nf90_put_var(idnc, idallvar(j), realvar);if (iret .ne. nf90_noerr) call handle_err(iret) !写入各变量
elseif(ctlvarflag(j)==3)then
read(10)realvar3d
write(*,*)'writing 3D',j
iret = nf90_put_var(idnc, idallvar(j), realvar3d,start=start,count=count);if (iret .ne. nf90_noerr) call handle_err(iret) !写入各变量
endif
enddo
close(10)
iret = nf90_close(idnc);if (iret .ne. nf90_noerr) call handle_err(iret)
write(*,*)'SUCCESS writing to NC file: '//trim(nameout)//'.nc'
stop ''
999 write(*,*)'Not found dat file:'//trim(nameofdat)//'=='
end
subroutine handle_err(errcode)
use netcdf
implicit none
!include 'netcdf.inc'
integer errcode
print *, 'Error: ', nf90_strerror(errcode)
stop 2
end
subroutine readctl(filectl,nameofdat,nameout,ctlvarflag,ix0,iy0,iz0,startx,starty,stepx,stepy,ivar,chvarname,maxitem,undef,if3d,levels,maxlev)
character*(*) filectl,nameofdat,nameout,chvarname(2,maxitem),ch*200,ch1*30
real levels(maxlev)
integer ctlvarflag(maxitem)
if3d=0 !作为是否有3D数据的标志
ctlvarflag=-1
open(100,file=filectl,status='old')
read(100,'(a200)')ch
ilen=len_trim(ch)
if(ch(ilen:ilen)<'!')ch(ilen:ilen)='' !避免windows格式带来的回车换行带来的影响
nameofdat=ch(6:len_trim(ch)) !'dset ./AN...' 防止有/误作转义符
if(nameofdat(1:1)=='^')nameofdat=nameofdat(2:len_trim(nameofdat)) !忽略grads里的特有符号
100 read(100,'(a200)')ch !
if(ch(1:5)=='title' .or. ch(1:5)=='TITLE')goto 100 !忽略title
read(ch,*)ch1,undef
read(100,*)ch,ix0,ch,startx,stepx
read(100,*)ch,iy0,ch,starty,stepy
read(100,*)ch,iz0,ch,(levels(i),i=1,iz0) !可能按行排列,或本行随后排放
read(100,*) !tdef 暂时忽略时间序列
read(100,*)ch,ivar
if(ivar>maxitem)ivar=maxitem
do i=1,ivar
read(100,*)chvarname(1,i),i1,i2,chvarname(2,i)
if(i1/=0)then !三维场
ctlvarflag(i)=3
if3d=1
else
ctlvarflag(i)=2 !二维场
endif
enddo
close(100)
nameout=trim(nameofdat) !准备输出文件名,抛弃原路径和后缀
i=index(nameout,'/',BACK=.TRUE.) !抛弃原路径
if(i>0)nameout=nameout(i+1:200)
!write(*,*)nameout(i+1:i+10)
j=index(nameout,'.',BACK=.TRUE.) !抛弃后缀
if(j>0)nameout(j:200)=''
!write(*,*)ivar,'=='//trim(nameofdat)//'==>'//trim(nameout)//'=='
do i=1,ivar
write(*,'(2i4,a,a20,2x,a)')i,ctlvarflag(i),'D',trim(chvarname(1,i)),trim(chvarname(2,i))
enddo
end
|
|