2016-07-15 70 views
1

我有一个模块中的几个数组变量是动态的,稍后分配给模块外的两个子例程之一。但是,在一个子程序中,我希望数组是一维的,而在另一个子程序中,我希望它是二维的。动态数组排名

原则上我希望在模块中这样的事情,但我不相信这是可能的声明区域?:

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。我只是希望避免这种情况。

+2

您可以使用执行该作业的子例程来重载'allocate'语句。 Fortran 90年龄将近26岁。你使用什么编译器?如果使用现代的Fortran(2003+)编译器,我建议定义派生的数据类型,同时使用2维和3维可分配类型组件以及相应的类型绑定过程。 Fortran 90不允许这样做,相反你必须使用容易发生内存泄漏的指针。 – jlokimlin

+2

我不明白你的问题。数组在主程序或模块中的外观如何?那里是1D还是2D?主程序或模块是否关心子程序如何处理它(1D或2D)?也许你可以使用简单的存储关联,但你应该显示更多的代码。 Ceterum censeo'kind = 8'很丑,臭和邪恶http://stackoverflow.com/a/856243/721644 –

+0

@jlokimlin编译器不是问题,但不幸的是,这是一个包含多个用户的大型代码库,所以对于在可预见的将来,它将不得不成为Fortran90。 – Michael

回答

1

我认为“古代”的方式做这样的事情是通过第一个元素,而不是整个阵列和阵列的单独大小:

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 
+0

不是今天撒旦!假设阵列的威力迫使你!为什么不传递'array(:)'并使用查询函数's = size(array)' – jlokimlin

+0

我还没有试过。你可以传递一个二维数组到一个子程序,期望一维数组并获得正确的大小? – chw21

+0

当使用'pointer'或'allocatable'属性定义数组时,语法与延迟形状数组的语法相同。见:http://stackoverflow.com/questions/38140951/fortran-subroutine-returning-wrong-values/38154225#38154225 – jlokimlin

0

“你能传递一个二维数组需要一维数组并获得正确大小的子程序?“

您可以使用重塑,但如果您的代码是依靠编译器来帮助,然后2D到1D是dicey。你可以在之前和之后使用RESHAPE ...或者你可以有2个例程,我们可以调用set1d和set2d。 然后在模块中,您可以选择您想要使用的模型。你可以有整数,浮点数,复数,字节。

您将调用数组$集(数组,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 

对于示例: 如果(选项1),然后 实(KIND = 8),可分配:: ARR1(:) 其他 实(KIND = 8),可分配:: 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 
+1

'kind = 4'和'kind = 8'真的很丑。不要将其用作良好代码的示例。 –

+0

你确定你可以结合ALLOCATABLE和CONTIGUOUS吗?一个暗示另一个。 ALIGN将只被一个特定的编译器所支持 –

+1

'ASUUME_ALIGND'看起来不正确,Fortran标识符名称中不允许有'$'。 –