将NetCDF写为变量作为时间的函数

时间:2015-01-01 18:55:36

标签: fortran fortran90 netcdf

我试图修改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

1 个答案:

答案 0 :(得分:2)

您需要做的是定义nf90_unlimited长度的时间维度。这将允许您一次将一个二维数组写入一个三维数组,并且不指定此数组的长度。使用startcount可选的伪参数进行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

我在大多数程序中所做的是创建文件并在开头定义维度和变量,然后在循环中写入字段。如果您的模拟需要很长时间,并且您希望能够在模拟过程中查看输出,请执行模型求解器内部的打开/写入/关闭步骤。