Netcdf和fortran结构

Netcdf和fortran结构,fortran,structure,netcdf,Fortran,Structure,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 现在我创建一个对象类型(custom2)::pntr 是否可以将自定义结构中的所有数据直接写入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
现在我创建一个对象类型(custom2)::pntr


是否可以将自定义结构中的所有数据直接写入netcdf格式,使所有组件(即a、b、c、d、e)的名称相同。当然这是使用pntr(object)。HDF5中的任何解决方案也是受欢迎的。提前感谢

原则上,是的,这在NetCDF4中是可能的;您正在查找手册的这一部分

但是,对它的支持不够好,可能会导致问题(甚至在F90中,您可能最终不得不使用f77接口)。这是我的第一次尝试,我无法编译,因为F90绑定不允许nf90_put_var调用。还要注意的是,计算偏移量是一个神奇的过程,这在Fortran中是非常重要的(但如果您也在使用MPI…,则可以使用MPI_Get_Address)。loc()是一个常见但非标准的函数,允许您执行此操作,如果您信任指针数学,还可以使用iso_c_绑定和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

谢谢你的回答。但是我对这个代码有一些疑问。例如,我必须尝试编译上面的代码。正如你所说,我注意到了一些错误。第一个错误是您提到的abt nf90_put_var。我不明白你所说的fortran绑定是什么意思。由于cvars是一个结构而不是数组,是否可以编写多个语句,如stat=nf90\u put\u var(file\u id,cvar\u id,cvars%a)等等。testlen=inquire(iolength=test)1错误:关键字参数要求在(1)处为过程“inquire”提供显式接口。我从未使用过这个命令,用谷歌搜索过该命令,但在理解错误方面不是很成功,你能解释一下偏移功能吗?或者至少这些行testlen=inquire(iolength=test)allocate(copy(testlen))copy=transfer(test,copy)是的,我确实使用MPI。那么我该如何在这里实现这个MPI_地址呢。我需要完全理解这个概念才能继续。谢谢你的帮助:inquire:你需要一个足够现代的编译器(如GCC4.6.x)来使用inquire的方式;我想你也可以用bit_size(),至于偏移量;您必须找出每个字段在数据结构中的起始位置。在这个简单的例子中——所有内容都是相同的4字节类型——很可能所有内容都是有序的,并且结构中没有填充;但是编译器可以自由地移动东西以获得性能。(另一方面,您可以使用序列限定符来确保按照预期的方式布置内容,但可能会对性能造成重大影响)。在这里,我只是标记字段,将它们复制到大小合适的实数数组中,然后查找它们。