【问题标题】:Write in NetCDF as a variable as a function of time在 NetCDF 中写入作为时间函数的变量
【发布时间】:2015-01-04 01:35:46
【问题描述】:

我正在尝试修改 Fortran 90 代码,该代码以 NetCDF 经典格式将二维数组写入输出。我希望该变量具有额外的时间维度(即,它将是一个 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

【问题讨论】:

  • 您给出的例程是针对 2D 阵列...您对 3D 阵列进行了哪些尝试?你得到什么错误?就目前而言,您的问题太宽泛了

标签: fortran fortran90 netcdf


【解决方案1】:

你需要做的是定义nf90_unlimited长度的时间维度。这将允许您一次将一个切片的二维数组写入 3 维数组,并使该数组的长度未指定。在nf90_put_var 调用中使用startcount 可选的虚拟参数来指定写入二维切片的位置。

! 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

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

【讨论】:

  • 谢谢@milancurcic。这正是我需要的,我会试一试。在 NetCDFIf 中,如果我想在运行时查看输出,是否必须在使用 MATLAB 分析之前关闭文件?
  • BTW - 每次调用“nf90_put_var”时哪个调用命令对应于打开文件? (我认为我不应该重复使用 'nf90_create')。
  • @Jacob 分别使用nf90_opennf90_close 打开和关闭文件。我相信您需要关闭文件才能读取它,但是,我注意到 ncview 可以在 NetCDF 文件处于打开状态并被写入时读取它们。试试看。另外,在线查找 Fortran NetCDF 用户指南。非常有用。
  • @milancurcuc - 感谢您的帮助。我写了一个模块(Module_NetCDF),方便以后用户查询。
  • 非常感谢您的示例。 超级很有用。试图让我的模型打印出 netcdf 结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-01
  • 2013-02-19
  • 2021-12-06
  • 2021-11-05
  • 2020-10-27
  • 1970-01-01
相关资源
最近更新 更多