2011-08-03 157 views
3

我是Fortran新手。我正在嘗試編寫一個子程序,它將從主程序中取出四個參數,然後向主程序輸出一個數組,該數組涉及最初傳入的四個參數。什麼是一個好的/聰明的方法來執行此操作?聰明的方式在Fortran中傳遞參數90

例如,在我下面的測試程序,我創建了四個實變量(abcd)在主程序中。然後我將這些實際變量傳遞給一個名爲mysub的子程序。我希望mysub能夠接受a,b,cd,使用它們填充名爲o的2乘2陣列,然後將o發送到主程序,以便在那裏顯示(以及可能的修改)。所以,我試過如下:

SUBROUTINE mysub(w,x,y,z) 
    IMPLICIT NONE 
    REAL, INTENT(IN) :: w, x, y, z 
    REAL, DIMENSION(:,:), ALLOCATABLE, INTENT(OUT) :: o 

    ALLOCATE(o(2,2)) 
    o(1,1)=w 
    o(1,2)=x 
    o(2,1)=y 
    o(2,2)=z 
END SUBROUTINE mysub 
END MODULE testsubs 

PROGRAM test 
    USE testsubs 
    IMPLICIT NONE 
    REAL :: a=1.1, b=2.2, c=3.3, d=4.4 

    CALL mysub(a, b, c, d) 

    PRINT *, o(1,1), o(1,2) 
    PRINT *, o(2,1), o(2,2) 
END PROGRAM test 

不過,我得到以下錯誤:

test.f90:10.53: 

    REAL, DIMENSION(:,:), ALLOCATABLE, INTENT(OUT) :: o 
                1 
Error: Symbol at (1) is not a DUMMY variable 

我將此解釋爲,編譯器不知道什麼o是,因爲o不在子程序頭中的參數列表:SUBROUTINE mysub(w,x,y,z)。所以我可能需要在該標題中包含o。所以,我接下來請嘗試以下(這裏,我表示使用!...修改或補充):

SUBROUTINE mysub(w,x,y,z,o) !... 
    IMPLICIT NONE 
    REAL, INTENT(IN) :: w, x, y, z 
    REAL, DIMENSION(:,:), ALLOCATABLE, INTENT(OUT) :: o 

    ALLOCATE(o(2,2)) 
    o(1,1)=w 
    o(1,2)=x 
    o(2,1)=y 
    o(2,2)=z 
END SUBROUTINE mysub 
END MODULE testsubs 

PROGRAM test 
    USE testsubs 
    IMPLICIT NONE 
    REAL :: a=1.1, b=2.2, c=3.3, d=4.4 
    REAL, DIMENSION(:,:), ALLOCATABLE :: o !... 

    CALL mysub(a, b, c, d, o) !... 

    PRINT *, o(1,1), o(1,2) 
    PRINT *, o(2,1), o(2,2) 
    DEALLOCATE(o) !... 
END PROGRAM test 

這似乎做工精細,我也得到了正確的輸出:

1.1000000  2.2000000 
    3.3000000  4.4000001 

不過,我的問題是,這是做這件事的好方法嗎?在這個工作例子中,我在主程序中聲明子程序中的數組o均爲。這似乎可能造成混亂,因爲我認爲,這意味着我需要照顧那個要麼子程序主程序分配o(但不,我認爲,爲了避免錯誤消息)。有沒有更聰明的方法來做到這一點 - 從子程序發送數組到主程序?感謝您的時間。

回答

3

你的解決方案,使「o」的意圖(out)的論點是很好的。如果沒有「o」作爲參數,則子程序中的變量「o」和主程序中的變量「o」之間沒有連接,因此在主程序中沒有聲明或分配該變量。另一個解決方案(除了由@ ja72提供的解決方案之外)將改變你的方法:將「o」作爲子程序的intent(inout)參數並將其分配到主程序中。可能的優點:分配和釋放在代碼中更接近並配對。可能的缺點:根據程序邏輯和設計,子程序可能最爲人所知。

P.S.如果您在主程序中分配數組,並且實際上不在子例程中使用數組的可分配屬性(即,您不分配或取消分配),那麼您不必使用allocatable屬性來聲明它在子例程中 - 一個有用的簡化。在這種情況下,「intent(out)」可能是合適的。但是,如果您在主程序中分配數組並希望將該狀態傳遞給子例程,則參數狀態不能爲「intent(out)」。 「intent(out)」在進入過程時自動釋放參數。

1

如果你想返回一個數組,你可以一)符合INTENT(OUT)喜歡你的例子#2分配子中加入的參數,或者b)創建功能和外部分配數組:

FUNCTION myfun(w,x,y,z,n,m) 
IMPLICIT NONE 
INTEGER, INTENT(IN) :: n,m 
REAL, DIMENSION(n,m) :: myfun 
REAL, INTENT(IN) :: w,x,y,z 

    myfun(1,1)=w 
    myfun(1,2)=x 
    myfun(2,1)=y 
    myfun(2,2)=z 

END FUNCTION 
END MODULE testsubs 

PROGRAM test 
    USE testsubs 
    IMPLICIT NONE 
    REAL :: a=1.1, b=2.2, c=3.3, d=4.4 
    REAL, DIMENSION(:,:), ALLOCATABLE :: o !... 

    ALLOCATE(o(2,2)) 
    o = myfun(a,b,c,d,2,2) 

    PRINT *, o(1,1), o(1,2) 
    PRINT *, o(2,1), o(2,2) 
    DEALLOCATE(o) !... 
END PROGRAM test 

其實我認爲你的解決方案更清潔。

1

從你的問題中不清楚你是否事先知道數組的大小,但是如果你這樣做,在同一個地方分配和釋放數組通常是一個好習慣,甚至更好的是儘可能讓編譯器分配內存。

我會怎麼做:

  • 如果大小是在編譯時已知: 聲明數組中的主程序,在一個子程序使用intent(out)

  • 如果大小隻在運行時已知: 分配在主程序中,在主程序中的子程序和釋放使用intent(out)

由於需要複製輸出,所以函數最適合小輸出。