我在模块中有一些动态的数组变量,后来在模块外部的两个子程序之一中分配。但是,在一个子程序中,我希望数组为1D,在另一个子程序中,我希望它是2D。
原则上我会在模块中想要这样的东西,但我不相信这在声明区域是可行的吗?:
if (option1) then
real (kind=8), allocatable :: arr1(:)
else
real (kind=8), allocatable :: arr1(:,:)
endif
在可分配的声明中是否有一种方法可以使维度具有动态性?
编辑1:我这样做的原因是我在现有代码库中添加了一个新的子程序,但我希望向后兼容。 arr1仅由两个独立的子程序使用,主程序根本不使用它。以下是一些更完整的代码,显示了这个想法:
program myprog
use inputs
call read_inputs
if (option1) then
call do1
else
call do2
endif
contains
subroutine read_inputs
use inputs
use mymod
!!!read from file .logical. option1, integers N1, N2
!allocate arrays
if (option1) then
else
endif
end subroutine read_inputs
subroutine do1
use inputs
use mymod
allocate(arr1(N1))
!do stuff with arr1
end subroutine do1
subroutine do2
use inputs
use mymod
allocate(arr1(N1,N2))
!do stuff with arr1
end subroutine do2
end program
module inputs
logical :: option1
integer :: N1, N2
end module inputs
module mymod
use inputs
!!!!can I do something here to make the rank of arr1 dynamic? I don't think the following will work
if (option1)
real (kind=8), allocatable :: arr1(:)
else
real (kind=8), allocatable :: arr1(:,:)
endif
end module mymod
我可能在mymod中有两个单独的变量,arr1和arr1_new。我只是希望避免这种情况。
答案 0 :(得分:1)
我认为' olden'做这样的事情的方法是分别传递第一个元素而不是整个数组和数组的大小:
program dyn_array
implicit none
integer :: a(2, 3)
integer :: i
call set1d(a(1,1), size(a))
do i = 1, 3
write(*, '(2I4)') a(:,i)
end do
contains
subroutine set1d(array, s)
implicit none
integer, intent(in) :: s
integer, intent(out) :: array(s)
integer :: i
do i = 1, s
array(i) = 3 * i
end do
end subroutine set1d
end program dyn_array
答案 1 :(得分:0)
"你能否将2D数组传递给需要一维数组并获得正确尺寸的子程序?"
你可以使用reshape,但是如果你的代码依赖于编译器来帮助那么2D进入1D是很冒险的。你可以在之前和之后使用RESHAPE ......或者你可以有2个例程,我们可以调用set1d和set2d。 然后在模块中,您可以选择要使用的模块。你可以有整数(s),float(s),complex(s),byte。
你会CALL Array $ Set(Array,s)
MODULE Stuff
PUBLIC :: Array$Set
PRIVATE
INTERFACE Array$Set
MODULE PROCEDURE Set1d_Float, Set1D_Double, set2D_Float, Set2D_Double
END INTERFACE Array$Set
CONTAINS
SUBROUTINE Set1D_Float(Array,S)...
!$DIR ATRIBUTES ASUUME_ALIGND:64 :: Array
REAL, DIMENSION(:,:), CONTIGUOUS, INTENT(INOUT) :: Array
REAL, DIMENSION(:,:), INTENT(IN ) :: S
REAL, DIMENSION(2) :: Shapez
...
Shapez = Shape(Array)
DO I = 1, Shapez(1)
DO J = 1, Shapez(2)
...
END SUBROUTINE Set1D_Float
END MODULE Stuff
对于你的例子: if(option1)然后 real(kind = 8),allocatable :: arr1(:) 其他 real(kind = 8),allocatable :: arr1(:,:) ENDIF
我会建议:
!DIR ATTRIBUTES ALIGN:64 :: Arr1
REAL, DIMENSION(:), ALLOCATABLE :: Arr1
...
if (option1) then
ALLOCATE(Arr1(<#>))
else
ALLOCATE(Arr1(<#>*<#2>))
RESHAPE(Arr1, SHAPE=/(#1,#2)) !Check the syntax
endif
CALL Array$Set(Arr1,s) !It'll find the right one...
!... at the bottom ...
IF(ALLOCATED(Arr1)) DEALLOCATE(Arr1)
END PROGRAM