gpt4 book ai didi

fortran - Netcdf 和 Fortran 结构

转载 作者:行者123 更新时间:2023-12-03 05:00:21 25 4
gpt4 key购买 nike

我有这个 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 是可能的;您正在寻找 User Defined Data Types手册部分。

但是,对它的支持很差,可能会导致问题(即使在 F90 中,您最终也可能不得不使用 f77 接口(interface))。这是我真正的第一次尝试,我无法编译它,因为 F90 绑定(bind)不允许 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

关于fortran - Netcdf 和 Fortran 结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6924073/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com