2016-07-15 36 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標識符名稱中不允許有'$'。 –