2011-08-03 5 views
3

이 포트란 구조가 있습니다. 그런 다음Netcdf 및 Fortran 구조

type custom 
    real :: a,b 
    real,dimension(20) ::c,d 
    real,dimension(20,50) :: e 
end type custom 

나는이

type custom2 
    type(custom):: data 
end type custom2 

같은 다른 구조가 지금은

PNTR 개체 유형 (CUSTOM2를) :: 만들어 가지고는 가능한 구조 정의에서 모든 데이터를 작성하는 것입니다 (즉, a, b, c, d, e)의 모든 이름을 동일하게 netcdf 형식으로 직접 변환 할 수 있습니다. 물론 이것은 pntr (object)를 사용하고 있습니다. HDF5에서이 모든 솔루션도 환영합니다. 미리 감사드립니다.

답변

2

원칙적으로 NetCDF4에서는 가능합니다. 설명서의 User Defined Data Types 섹션을 찾으십시오.

그러나 지원이 충분하지 않아서 문제가 발생할 수 있으며 결국 F90에서도 f77 인터페이스를 사용해야 할 수 있습니다. F90 바인딩이 nf90_put_var 호출을 허용하지 않기 때문에 컴파일 할 수없는 첫 해킹입니다. 또한 마술은 오프셋을 계산하는 데있어 모두 중요합니다. Fortran에서는 그다지 중요하지 않습니다 (그러나 MPI를 사용하고 있다면 MPI_Get_Address를 사용하면됩니다). loc()은 이것을 할 수있는 공통적이지만 비표준 함수이며 포인터 계산을 신뢰하면 iso_c_bindings 및 c_loc()을 사용할 수도 있습니다.

PROGRAM netcdf_userdeftypes 
    USE netcdf 
    implicit none 

    type custom 
     real :: a,b 
     real,dimension(20) ::c,d 
     real,dimension(20,50) :: e 
    end type custom 

    integer :: stat 
    integer :: i 
    integer, parameter :: ncvars=5 
    type(custom) :: cvars(ncvars) 
    integer :: ctype_id, cvar_id, file_id, dim_id 
    integer :: aoff, boff, coff, doff, eoff 

    stat = nf90_create(path="test.nc4", cmode=ior(NF90_CLOBBER,NF90_NETCDF4), ncid=file_id) 
    stat = nf90_def_dim(file_id, 'Num Custom Vars', ncvars, dim_id) 

    stat = nf90_def_compound(ctype_id, (2+2*20+1*(20*50))*4, 'custom type', ctype_id) 

    call calcoffsets(aoff, boff, coff, doff, eoff) 
    stat = nf90_insert_compound(file_id, ctype_id, 'a', aoff, NF90_REAL) 
    stat = nf90_insert_compound(file_id, ctype_id, 'b', boff, NF90_REAL) 
    stat = nf90_insert_array_compound(file_id, ctype_id, 'c', coff, NF90_REAL, 1, 20) 
    stat = nf90_insert_array_compound(file_id, ctype_id, 'd', doff, NF90_REAL, 1, 20) 
    stat = nf90_insert_array_compound(file_id, ctype_id, 'e', eoff, NF90_REAL, 2, 20*50) 

    stat = nf90_def_var(file_id, 'custom variable', ctype_id, [dim_id], cvar_id) 
    stat = nf90_enddef(file_id) 

    do i=1,ncvars 
     cvars(i)%a = ncvars*10+1 
     cvars(i)%b = ncvars*10+2 
     cvars(i)%c = ncvars*10+3 
     cvars(i)%d = ncvars*10+4 
     cvars(i)%e = ncvars*10+5 
    enddo 

    stat = nf90_put_var(file_id, cvar_id, cvars) 

    stat = nf90_close(file_id) 

CONTAINS 
    ! there has to be a better way to do this 
    ! loc() is common, and c_loc() could in principle 
    ! be used... 
    SUBROUTINE calcoffsets(aoff, boff, coff, doff, eoff) 
     implicit none 
     integer, intent(out) :: aoff, boff, coff, doff, eoff 

     type(custom) :: test 
     integer :: i,testlen 
     type(custom), pointer :: tp 
     real, allocatable, dimension(:) :: copy 

     test % a = 1. 
     test % b = 2. 
     test % c = 0. 
     test % c(1) = 3. 
     test % d = 0. 
     test % d(1) = 4. 
     test % e = 0. 
     test % e(1,1) = 5. 

     testlen = inquire(iolength=test) 
     allocate(copy(testlen)) 
     copy = transfer(test, copy) 

     do i=1,testlen 
      if (copy(i) == 1.) aoff = i-1 
      if (copy(i) == 2.) boff = i-1 
      if (copy(i) == 3.) coff = i-1 
      if (copy(i) == 4.) doff = i-1 
      if (copy(i) == 5.) eoff = i-1 
     enddo 

    END SUBROUTINE calcoffsets 

END PROGRAM netcdf_userdeftypes 
+0

답변 해 주셔서 감사합니다. 그러나이 코드에 대해 몇 가지 의문점이 있습니다. 예를 들어, 위의 코드를 컴파일해야했습니다. 내가 말한대로 몇 가지 오류를 발견했다. 처음 언급 한 오류는 abt nf90_put_var입니다. 나는 당신이 fortran 바인딩에 의해 의미했던 것을 이해하지 못했습니다. cvars는 배열이 아니고 구조체이기 때문에 stat = nf90_put_var (file_id, cvar_id, cvars % a) 등과 같이 여러 개의 명령문을 작성할 수 있습니까? – user665903

+0

두 번째로 나는 이와 같은 본질적인 명령을 묻는 데있어 오류가 발생했습니다.1 오류 : (1) 에서 '문의'절차에 대한 명시적인 인터페이스가 키워드 인수에 필요합니다.이 명령을 사용한 적이 없으며 오류를 이해하는 데 성공하지 못했습니다. – user665903

+0

셋째, 수 있습니까? 오프셋 기능이나 적어도이 줄을 설명하십시오. testlen = inquire (iolength = test) copy = transfer (test, copy) 네, 저는 MPI를 사용합니다. 그렇다면이 MPI_Address를 어떻게 구현할 수 있습니까? 계속 진행하려면이 개념을 완전히 이해해야합니다. ur 도움말에 감사드립니다 – user665903