2016-06-28 83 views
0

前言存儲多維陣列

的Fortran程序,我正在寫應處理取決於ndims 1D,2D和3D的問題,它可以是1,2或3並從輸入文件中讀取。

在這些情況下的量/所關注IES可以(一個可以被命名爲phi)存儲在數組

    dimsALLOCATABLE(:)ALLOCATABLE(:,:)ALLOCATABLE(:,:,:))的
  1. 或在等級陣列3(ALLOCATABLE(:,:,:),第三維在2D中等於1或者第二和第三維在1D中等於1);

這兩種情況在this answer都有很好的解釋。第一種方法對我來說似乎更加優雅,但在下面我假設第二種方法,這絕對簡單。

這些量必須由幾個子程序上進行操作(如mysub)沿ndims尺寸(沿「鉛筆」應該給圖形的想法),所以我應該叫像

SELECT CASE (ndims) 

! 3D case 
CASE (3) 
    DO j = ... 
    DO k = ... 
     CALL mysub(phi(:,j,k)) 
    END DO 
    END DO 
    DO i = ... 
    DO k = ... 
     CALL mysub(phi(i,:,k)) 
    END DO 
    END DO 
    DO i = ... 
    DO j = ... 
     CALL mysub(phi(i,j,:)) 
    END DO 
    END DO 

! 2D case 
CASE (2) 
    DO j = ... 
    DO k = ... 
     CALL mysub(phi(:,j,1)) 
    END DO 
    END DO 
    DO i = ... 
    DO k = ... 
     CALL mysub(phi(i,:,1)) 
    END DO 
    END DO 

! 1D case 
CASE (1) 
    DO j = ... 
    DO k = ... 
     CALL mysub(phi(:,1,1)) 
    END DO 
    END DO 
END SELECT 

實際問題

任何人都可以建議我(或幫助我設計!)一種不同的存儲方式phi(可能涉及派生數據類型?),以便我可以摺疊前面的代碼如下?

DO id = 1, ndims 
    CALL mysub2(phi,id) 
END DO 

(這裏​​作用mysub的地方。)

所以,問題是我應該如何存儲披,這樣我就可以用第二個替代第一碼?

也許我可以回到前言,並決定按照1點,在這種情況下會更容易編寫一個通用的接口。我認爲,這只是一種「隱藏」SELECT CASE會做什麼的方法。哪兩個(SELECT CASE /通用INTERFACE)會更有效率?

這些是面對這個問題只有兩個辦法?

+0

這正在成爲一種常見的東西。最近問昨天 - http://stackoverflow.com/questions/38058080/fortran-choosing-the-rank-of-an-allocatable-array。 –

+0

問題有明顯的關聯,但這個問題的答案不會回答這個:這個問題,如果我理解正確的,是關於如何選擇一個數組的等級;我的問題更多地是關於「編寫不依賴於其所操作陣列的等級的代碼的最佳方式」。 –

回答

1

也許是我誤會了,不過我想答案的具體問題是不能對存儲或披聲明所有的任何變化。

在原始代碼中,三維數據切片中沿着第一維度被處理,則第二,然後第三個(從用於存儲數據的陣列的等級區分的數據的等級)。二維數據沿着第一個處理,然後第二個和一維數據沿着第一個處理。

ID爲1將在數據的維數

所以,請考慮以下實施​​:

SUBROUTINE mysub2(phi, id) 
    TYPE(pink_elephant), INTENT(IN) :: phi(:,:,:) 
    INTEGER, INTENT(IN) :: id 

    INTEGER :: i, j, k 

    SELECT CASE (id) 
    CASE (1) 
    DO j = ... 
     DO k = ... 
     CALL mysub(phi(:,j,k)) 
     END DO 
    END DO 

    CASE (2) 
    DO i = ... 
     DO k = ... 
     CALL mysub(phi(i,:,k)) 
     END DO 
    END DO 

    CASE (3) 
    DO i = ... 
     DO j = ... 
     CALL mysub(phi(i,j,:)) 
     END DO 
    END DO 

    END SELECT 
END SUBROUTINE mysub2 

~~

通用接口,可以隨時在「編譯時」來解決 - 可以通過查看代碼中的聲明來確定將由特定CALL語句或函數引用調用的特定過程(不是類型綁定)或綁定(類型綁定)。

如果您遇到了「運行時間」信息將影響過程選擇的情況,那麼必須有一些其他可執行機制,除了通用解析之外或附加解決方案 - 即使因此聲明後,選擇的情況下,動態調度,等,等,等

詢問通用的分辨率是否爲可執行的決定更有效的是沒有什麼特殊意義 - 它們是不同的東西。

+0

(然後,也許 「** **高效」 是不正確的字。)在你的代碼'SELECT CASE(爲ndims)'每次'mysub2'是'CALL'ed執行。如果是使用'SELECT CASE(爲ndims)'(類似於什麼在我掛了答案完成)選擇phi'的'軍銜,比'INTERFACE'塊可用於調用3個不同的'SUBROUTINE's爲3不同的隊伍。這不會更快**嗎? –

+1

通用接口只是將不同的過程放在同一標識符後面的命名便利性。除了輔助功能之外,您可以簡單地將通用名稱更改爲通用在編譯時解析的相關特定名稱,並獲得完全相同的行爲。它們的使用不是執行效率的問題,它們的使用是一個問題:「我輸入哪些字符以引用特定的過程」。你是否真的問過「某​​個嵌套迭代結構的哪個層次能夠做出特定決策是最有效的」? – IanH

+0

也許我有點困惑。你說我可以簡單地將通用名稱更改爲相關的特定名稱。這似乎很簡單!我認爲SELECT CASE會更慢。我錯了嗎?如果是這樣,爲什麼? (關於引號中的最後一個問題,我沒有明白。) –

1

你可能想是這樣的:

program test 

    integer :: j,ndims 
    integer :: n ! rank of each dimension, could also be read from input an allocated separately 

    type arr 
     real(8) :: x(n) ! one array for each dimension 
    end type 

    type(arr),allocatable :: phi 

    read(*,*) ndims 
    allocate(phi(ndims)) 

    do j=1,ndims 
     call mysub(phi(j)%x) ! acts on the array in dimension j 
    end do 

contains 

    subroutine mysub(x) 
    ... 
    end subroutine 

end program 
+0

那麼,這可能是一個起點。我希望你能進一步提供幫助。你的答案有效地顯示瞭如何對'ndims'維數進行'DO'循環。另一方面,'arr'不會包含'phi'所包含的相同信息。 –

+0

我在實際問題中增加了一些細節。 –

+0

是的,我想我回答得有點快^^。 – PeMa