2015-01-01 6 views
0

NetCDF 클래식 형식의 출력에 2D 배열을 쓰는 Fortran 90 코드를 수정하려고합니다. 변수에 시간에 대한 추가 치수 (예 : 3D 변수)를 지정하여 모델의 통합 시간 동안 해당하는 모든 시간 단계를 인쇄하고 싶습니다.시간의 함수로 NetCDF에 변수로 쓰기

어떻게 진행되고 있는지 잘 모르겠습니다. 가능한 한 효율적으로 (최소한의 파일 크기로) 제안 해 주시면 감사하겠습니다.

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

당신이 준 루틴은 2D 배열을위한 것입니다 ... 3D 배열을 위해 무엇을 시도 했습니까? 어떤 오류가 발생합니까? 지금은 귀하의 질문이 너무 광범위합니다 *! –

답변

1

당신이해야 할 일은 nf90_unlimited 길이의 시간 차원을 정의하는 것입니다. 이렇게하면 한 번에 한 차원 씩 2 차원 배열을 3 차원 배열에 쓴 다음이 배열의 길이를 지정하지 않을 수 있습니다. 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 

은 내가 내 대부분의 프로그램에서 할 것은 파일을 생성하고 처음에 치수 및 변수를 정의하고, 그 후에 루프의 필드를 작성합니다. 시뮬레이션에 오랜 시간이 걸리고 진행중인 시뮬레이션 중에 출력을보고 싶다면 모델 해석기 do-loop 내부에서 열기/쓰기/닫기 단계를 수행하십시오.

+0

감사합니다. @milancurcic. 이것은 내가 필요로하는 것이고, 나는 그것을 시도 할 것이다. NetCDFIf에서 런타임 중에 출력을보고 싶다면 MATLAB을 사용하여 파일을 분석하기 전에 파일을 닫아야합니까? – Jacob

+0

BTW - 'nf90_put_var'호출 할 때마다 호출 명령이 파일 열기에 해당합니까? (나는 'nf90_create'를 반복해서 사용해서는 안된다고 가정). – Jacob

+0

@Jacob 파일을 열고 닫을 때'nf90_open'과'nf90_close'를 사용하십시오. 그러나 파일을 읽으려면 파일을 닫아야한다고 생각합니다. 그러나 ncview는 NetCDF 파일을 열어 놓은 상태에서 읽을 수 있습니다. 시도 해봐. 또한 Fortran NetCDF 사용자 안내서를 온라인으로 찾아보십시오. 그것은 매우 유용합니다. – milancurcic