我编写了一个程序,它读取包含多维数据的文件(最常见的是3D,但也可能出现2D)。为了提高简洁性,我想将数据存储在相同等级的数组中(或者假装为一个等级的数据),即使用三维数据进行3D数据等;麻烦的是程序只学习读取数据文件的维度。
目前,我将所有数据存储在排名为1的数组中,并根据元素的坐标计算该数组中每个元素的索引(这也是建议here)。但是,我也读过有关指针等级重新映射的内容,它看起来非常优雅,正是我一直在寻找的内容,因为它可以让我废弃我的数组索引确定程序(这可能远远低于后面的内容)场景)。然而,现在看起来我面临着与直接声明多维数组相同的问题 - 如何进行声明?同样,它需要有关排名的信息。
我如何使用指针等级重新映射或其他更合适的技术在运行时设置数组的等级 - 以防这种情况可以完成。或者我最好坚持我目前正在使用的排名单阵?
答案 0 :(得分: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
答案 1 :(得分:4)
我曾经问过类似的东西,即如何将二维数组视为一个维度,请参阅此处:changing array dimensions in fortran。
答案是关于指针的RESHAPE instrinsic,但是似乎没有办法使用相同的数组 name ,除非你使用子程序包装器,但是你需要回调来使用最终的子程序只有一个名字,所以问题变大了。
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
答案 2 :(得分: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
答案 3 :(得分: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数组的接口。你可以调用populate接口而不是调用单个子程序。它会自动选择相关的一个。