2

我编写了一个程序,它读取包含多维数据的文件(最常见的是 3D,但也可能出现 2D)。为了提高简单性,我想将数据存储在相同等级的数组中(或假装是一个),即使用 3D 数据的三维数组等;问题是程序只了解读取数据文件的维度。

目前,我将所有数据存储在一个排名为 1 的数组中,并根据元素的坐标计算该数组中每个元素的索引(这里也建议这样做)。但是,我还阅读了有关指针等级重新映射的内容,这看起来非常优雅,正是我一直在寻找的,因为它可以让我放弃我的数组索引确定程序(这可能远低于后面发生的事情)场景)。但是,现在看来我面临与直接声明多维数组相同的问题 - 如何进行声明?同样,它需要有关等级的信息。

我如何使用指针等级重新映射或其他更合适的技术在运行时设置数组的等级 - 以防万一这完全可以完成。还是我最好坚持我目前使用的排名一阵列?

4

4 回答 4

4

如果我理解正确,您在 1-D 数组中读取数据并希望将其分配给 2D 或 3D 数组,您只有在读取文件后才知道。为什么不将 2D 和 3D 数组都声明为可分配数组,并根据您的数据形状仅分配其中一个?您可以使用内部函数 RESHAPE 方便地执行此操作。

REAL,DIMENSION(:,:),  ALLOCATABLE :: arr2d
REAL,DIMENSION(:,:,:),ALLOCATABLE :: arr3d
...
! Read data into 1-D array, arr1d;
...
IF(L2d)THEN
  ALLOCATE(arr2d(im,jm))
  arr2d=RESHAPE(arr1d,(/im,jm/))
ELSEIF(L3d)THEN
  ALLOCATE(arr3d(im,jm,km))
  arr3d=RESHAPE(arr1d,(/im,jm,km/))
ENDIF
于 2011-09-21T16:40:34.213 回答
4

我曾经问过类似的问题,即如何将二维数组视为一维,请参见此处:更改 fortran 中的数组维度

答案是关于指针的 RESHAPE 本质,但是似乎没有办法使用相同的数组名称,除非您使用子例程包装器,但是您需要回调以使最终的子例程只有一个名称,因此问题变得更大。

program test
    real, allocatable :: data(:)
    allocate(data(n_data))
    ! read stuff, set is_2d and sizes
    if (is_2d) then
        call my_sub2(data, nX, nY)
    else
        call my_sub3(data, nX, nY, nZ)
    end if
end program test

subroutine my_sub2(data, nX, nY)
    real :: data(nx,nY)
    ! ...
end subroutine my_sub2

subroutine my_sub3(data, nX, nY, nZ)
    real :: data(nx,nY,nZ)
    ! ...
end subroutine my_sub3

编辑:作为替代方案,将第三个等级设置为 1:

program test
    real, allocatable, target:: data(:)
    real, pointer:: my_array(:,:,:)
    logical is_2d
    n_data = 100
    allocate(data(n_data))
    ! read stuff, determine is_2d and n
    if (is_2d) then
        i=n
        j=n
        k=1
    else
        i=n
        j=n
        k=n
    end if
    my_array(1:i,1:j,1:k) => data
    write(*,*) my_array
end program test

然后您将 2D 案例作为具有第三维 1 的特殊 3D 案例来处理。

EDIT2:另外,在将非连续数组传递给具有显式形状数组的子例程时要小心:http: //software.intel.com/sites/products/documentation/hpc/compilerpro/en-us/fortran/lin/compiler_f/optaps /fortran/optaps_prg_arrs_f.htm

于 2011-09-21T17:32:39.707 回答
4

您可以像这样使用 EQUIVALENCE 语句:

Program ranks
    integer a_1d(12)
    integer a_2d(2, 6)
    integer a_3d(2, 2, 3)

    equivalence (a_1d, a_2d, a_3d)

    ! fill array 1d
    a_1d = (/1,2,3,4,5,6,7,8,9,10,11,12/)

    print *, a_1d

    print *, a_2d(1,1:6)
    print *, a_2d(2,1:6)

    print *, a_3d(1,1,1:3)
    print *, a_3d(2,1,1:3)
    print *, a_3d(1,2,1:3)
    print *, a_3d(2,2,1:3)

end program ranks
于 2011-09-22T13:17:43.643 回答
0

您可以为不同等级的数组编写一个子程序并创建一个接口在示例中,我展示了如何使用接口语句填充不同数组的数组

program main 
    use data 
    implicit none 
    real,dimension(:,:,:),allocatable::data 
    integer::nx,ny,nz
    nx = 5
    ny = 10
    nz = 7
    call populate(nx,ny,nz,data)
    print *,data
end program main `

数据模块在这里

module data  
  private 
  public::populate
  interface populate 
      module procedure populate_1d 
      module procedure populate_2d 
      module procedure populate_3d 
  end interface
 contains 
   subroutine populate_1d(x,data)
       implicit none 
       integer,intent(in)::x
       real,dimension(:),allocatable,intent(out):: data
       allocate(data(x))
       data=rand()
   end subroutine populate_1d 
   subroutine populate_2d(x,y,data)
       implicit none 
       integer,intent(in)::x,y
       real,dimension(:,:),allocatable,intent(out):: data
       allocate(data(x,y))
       data=rand()
   end subroutine populate_2d 
   subroutine populate_3d(x,y,z,data)
       implicit none 
       integer,intent(in)::x,y,z
       real,dimension(:,:,:),allocatable,intent(out):: data
       allocate(data(x,y,z))
       data=rand()
   end subroutine populate_3d 
end module data 

有一个用于填充 1d、2d 和 3d 数组的界面。您可以调用填充接口而不是调用单个子例程。它会自动选择相关的。

于 2017-04-07T23:51:15.187 回答