简体   繁体   English

将1D数组传递到3D数组

[英]Pass 1D array to 3D array

I am using a API in Fortran which provides a routine for writing data. 我在Fortran中使用的API提供了用于写入数据的例程。 Let's say its name is api_write_data . 假设其名称为api_write_data This routine expects an array as argument which can be of dimension 1, 2 or 3. 此例程希望将数组作为参数,其维数可以为1、2或3。

I want to write a subroutine which works as wrapper for this API routine. 我想编写一个子例程,用作该API例程的包装器。 But therefore it is necessary for me to write a routine which can handle 1D, 2D or 3D arrays and can pass them correctly to the API routine. 但是因此,对于我来说,有必要编写一个例程,该例程可以处理1D,2D或3D数组并将其正确传递给API例程。 How can I do that? 我怎样才能做到这一点? Can I do that at all? 我能做到吗?

My approach was something like this, but it does not work: 我的方法是这样的,但它不起作用:

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

call api_write_data(array)

end subroutine write_data

However when I call this routine with for example an 1D array, I get the known error: 但是,当我使用例如一维数组调用此例程时,出现了已知错误:

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

Is there any way to do that kind of thing in Fortran? 有什么办法可以在Fortran中做这种事情? For me it is necessary to pass the Array as a 1D, 2D or 3D array to the write_data routine. 对我来说,有必要将数组作为1D,2D或3D数组传递给write_data例程。 However, I could pass the array as 1D array to api_write_data . 但是,我可以将数组作为一维数组传递给api_write_data

Do you have any idea how I could do that? 你知道我该怎么做吗?

You may use Fortran interface to define several versions of your routines: 您可以使用Fortran接口定义例程的多个版本:

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

Then these procedures can handle different types of input. 然后,这些过程可以处理不同类型的输入。 Then inside these procedures you may use the RESHAPE function to convert the input into a convenient shape so that all three can call a common subroutine that implements the logic of whatever you do. 然后,在这些过程中,您可以使用RESHAPE函数将输入转换为方便的形状,以便这三个函数都可以调用一个公共子例程,该子例程实现您所做的任何逻辑。

An alternative to the reshape function might be to have a 1D pointer towards the multi-dimensional array: reshape函数的替代方法可能是具有指向多维数组的一维指针:

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

You can pass the pointer as a one-dimensional array without making a copy. 您可以将指针作为一维数组传递而无需进行复制。 In fact, it should be as fast as passing the array itself. 实际上,它应该和传递数组本身一样快。 Of course, you need some way of telling the subroutine which shape the array has: 当然,您需要某种方法来告诉子例程数组具有哪种形状:

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

This also works the other way round... You can map a 1D array to a 3D pointer: 这也可以反过来工作...您可以将1D数组映射到3D指针:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM