将1D阵列传递给3D阵列

时间:2015-11-18 11:35:08

标签: arrays multidimensional-array fortran subroutine

我在Fortran中使用API​​,它提供了编写数据的例程。我们说它的名字是api_write_data。此例程需要一个数组作为参数,其大小可以是1,2或3。

我想编写一个子例程,作为此API例程的包装器。但是因此我有必要编写一个可以处理1D,2D或3D数组的例程,并且可以将它们正确地传递给API例程。我怎样才能做到这一点?我可以这样做吗?

我的方法是这样的,但它不起作用:

subroutine write_data(array)
implicit none
integer, dimension(:,:,:), intent(in):: array

call api_write_data(array)

end subroutine write_data

然而,当我用例如一维数组调用此例程时,我得到已知错误:

Error: Rank mismatch in argument 'array' at (1) (rank-3 and rank-1)

有没有办法在Fortran做那种事情?对我来说,有必要将数组作为1D,2D或3D数组传递给write_data例程。但是,我可以将数组作为一维数组传递给api_write_data

你知道我怎么能这样做吗?

2 个答案:

答案 0 :(得分:1)

您可以使用Fortran界面定义几个版本的例程:

interface write_data
  module procedure write_data_1d
  module procedure write_data_2d
  module procedure write_data_3d
end interface write_data

然后这些程序可以处理不同类型的输入。然后在这些过程中,您可以使用RESHAPE函数将输入转换为方便的形状,这样所有三个函数都可以调用一个公共子例程来实现您所做的任何逻辑。

答案 1 :(得分:1)

reshape函数的替代方法可能是指向多维数组的1D指针:

p(1:size(c)) => c(:,:,:)

您可以将指针作为一维数组传递而无需复制。实际上,它应该与传递数组本身一样快。 当然,你需要一些方法来告诉子程序数组的形状:

module test_mod
contains
  subroutine print_arr( arr, dimX, dimY, dimZ )
    integer,intent(in)  :: arr(:)
    integer,intent(in)  :: dimX, dimY, dimZ

    if ( dimZ == 0 ) then
      if ( dimY == 0 ) then
        ! 1D
        print *, "1D array provided"
        print *, "a(4) =", arr(4)
      else
        ! 2D
        print *, "2D array provided"
        print *, "a(1,2) =", arr((2-1)*dimX+1)
      endif
    else
      ! 3D
      print *, "3D array provided"
      print *, "a(1,2,1) =", arr( ((1-1)*dimY + (2-1))*dimX+1)
    endif
  end subroutine
end module

program test
use test_mod
  integer :: i
  integer, target   :: a(8)
  integer, target   :: b(4,2) 
  integer, target   :: c(2,2,2)
  integer, pointer  :: p(:)

  a = [ (i,i=1,8) ]
  b = reshape( a, [4,2] )
  c = reshape( a, [2,2,2] )

  p(1:size(a)) => a(:)
  call print_arr( p, 8, 0, 0 )

  p(1:size(b)) => b(:,:)
  call print_arr( p, 4, 2, 0 )

  p(1:size(c)) => c(:,:,:)
  call print_arr( p, 2, 2, 2 )
end program

这也可以反过来...你可以将1D数组映射到3D指针:

integer, pointer  :: p2(:,:,:)
!...
p2(1:4,1:2,1:1) => a