我试图修改Fortran 90代码,该代码以NetCDF经典格式将2D数组写入输出。我希望变量有一个额外的时间维度(即,它将是一个3D变量),在模型的积分时间内每隔一个相应的时间步骤打印它。
我不确定它是如何完成的;我感谢任何有关尽可能高效地进行此操作的建议(也是最小文件大小)。
subroutine writenetcdffile(array,argtitle)
use netcdf
implicit none
real, intent(IN), dimension(:,:) :: array
character*(*),intent(IN) :: argtitle
integer :: file_id, xdim_id, ydim_id
integer :: array_id
integer, dimension(2) :: arrdims
! character(len=*) :: argtitle = Flag_in
integer :: i, j
integer :: ierr
i = size(array,1)
j = size(array,2)
! create the file
ierr = nf90_create(path='test.nc', cmode=NF90_CLOBBER, ncid=file_id)
! define the dimensions
ierr = nf90_def_dim(file_id, 'X', i, xdim_id)
ierr = nf90_def_dim(file_id, 'Y', j, ydim_id)
! now that the dimensions are defined, we can define variables on them,...
arrdims = (/ xdim_id, ydim_id /)
ierr = nf90_def_var(file_id, 'Array', NF90_REAL, arrdims, array_id)
! ...and assign units to them as an attribute
ierr = nf90_put_att(file_id, array_id, "title", argtitle)
! done defining
ierr = nf90_enddef(file_id)
! Write out the values
ierr = nf90_put_var(file_id, array_id, array)
! close; done
ierr = nf90_close(file_id)
return
end subroutine writenetcdffile
MODULE Module_NetCDF
use netcdf
IMPLICIT NONE
integer :: file_id, xdim_id, ydim_id, tdim_id
integer :: array_id(5)
integer, dimension(3) :: arrdims
integer :: i, j
integer :: ierr
CONTAINS
SUBROUTINE NetCDF_Init(ICase)
IMPLICIT NONE
INTEGER :: ICase
SELECT CASE(ICase)
Case(1)
! create the file
ierr = nf90_create(path='test.nc', cmode = NF90_CLOBBER, ncid = file_id)
Case(2)
! Reopen the file for writing
ierr = nf90_open(path = "test.nc", mode = nf90_write, ncid = file_id)
if (ierr /= nf90_noerr) call check(ierr)
Case(3)
! close; done
ierr = nf90_close(file_id)
END SELECT
RETURN
END SUBROUTINE NetCDF_Init
SUBROUTINE NetCDF_Def(Array,ArrayTitle,ArrayUnits)
IMPLICIT NONE
real, intent(IN), dimension(:,:) :: Array
character(*),intent(IN) :: ArrayTitle(5)
character(*),intent(IN) :: ArrayUnits(5)
! Locals
integer :: k
i = size(Array,1)
j = size(Array,2)
! CALL NetCDF_Init(1)
! define the dimensions
ierr = nf90_def_dim(file_id, 'X', i, xdim_id)
ierr = nf90_def_dim(file_id, 'Y', j, ydim_id)
ierr = nf90_def_dim(file_id, 'Time', nf90_unlimited, tdim_id)
! now that the dimensions are defined, we can define variables on them,...
arrdims = (/ xdim_id, ydim_id, tdim_id /)
do k = 1,size(ArrayTitle)
ierr = nf90_def_var(file_id, ArrayTitle(k), NF90_REAL, arrdims, array_id(k))
! ...and assign units to them as an attribute
ierr = nf90_put_att(file_id, array_id(k), "Units", ArrayUnits(k))
enddo
! done defining
ierr = nf90_enddef(file_id)
RETURN
END SUBROUTINE NetCDF_Def
SUBROUTINE NetCDF_Write(Array,FlagTitle,NTime)
IMPLICIT NONE
real, intent(IN), dimension(:,:) :: Array
integer,intent(IN) :: NTime
character(*),intent(in) :: FlagTitle
! Locals
integer :: J_id
IF(FlagTitle.EQ.'ONECOND')THEN
J_id = 1
ELSEIF(FlagTitle.EQ.'MELTING')THEN
J_id = 2
ELSEIF(FlagTitle.EQ.'FREEZ_NEW')THEN
J_id = 3
ELSEIF(FlagTitle.EQ.'TFREEZ')THEN
J_id = 4
ELSEIF(FlagTitle.EQ.'DFREEZ')THEN
J_id = 5
ENDIF
CALL NetCDF_Init(2)
ierr = nf90_put_var(file_id, array_id(j_id), Array, start=[1,1,ntime], count=[i,j,1])
CALL NetCDF_Init(3)
RETURN
END SUBROUTINE
SUBROUTINE check(status)
IMPLICIT NONE
integer, intent ( in) :: status
IF(status /= nf90_noerr) THEN
PRINT *, trim(nf90_strerror(status))
STOP 2
ENDIF
END SUBROUTINE check
END MODULE Module_NetCDF
答案 0 :(得分:2)
您需要做的是定义nf90_unlimited
长度的时间维度。这将允许您一次将一个二维数组写入一个三维数组,并且不指定此数组的长度。使用start
和count
可选的伪参数进行nf90_put_var
调用,以指定写入2-d切片的位置。
! create the file
ierr = nf90_create(path='test.nc', cmode=NF90_CLOBBER, ncid=file_id)
! define the dimensions
ierr = nf90_def_dim(file_id, 'X', i, xdim_id)
ierr = nf90_def_dim(file_id, 'Y', j, ydim_id)
ierr = nf90_def_dim(file_id, 'Time', nf90_unlimited, tdim_id)
! now that the dimensions are defined, we can define variables on them,...
arrdims = (/ xdim_id, ydim_id, tdim_id /)
ierr = nf90_def_var(file_id, 'Array', NF90_REAL, arrdims, array_id)
! done defining
ierr = nf90_enddef(file_id)
! Time loop
do n = 1,nm
! Calculations go here
! Write out the values
ierr = nf90_put_var(file_id, array_id, array, start=[1,1,n], count=[i,j,1])
enddo
我在大多数程序中所做的是创建文件并在开头定义维度和变量,然后在循环中写入字段。如果您的模拟需要很长时间,并且您希望能够在模拟过程中查看输出,请执行模型求解器内部的打开/写入/关闭步骤。