我正在嘗試編寫一個用於最小化的通用子例程。因爲我想有一個通用的子程序,所以目標函數可以有不同的參數,不僅在名稱中,而且在維度中也是如此。所以我需要一種方法來傳遞參數結構(我使用的是單詞結構,因爲我的想法是使用類似於Matlab中的結構類型變量)。 我設法使用派生的數據類型,它工作得很好,但是當我在同一個程序中有兩個不同的目標函數時會出現問題。這是一個示例代碼:Fortran:將任意「結構」傳遞給模塊子例程
在主程序main.f90時:
MODULE MYPAR
IMPLICIT NONE
TYPE PARPASS1 !! Parameter passing structure 1
INTEGER :: a
REAL :: X(2,2)
END TYPE PARPASS1
TYPE PARPASS2 !! Parameter passing structure 2
REAL :: b
REAL :: Y(3)
END TYPE PARPASS2
END MODULE MYPAR
PROGRAM MAIN
USE MYPAR
USE MYLIB
IMPLICIT NONE
INTEGER :: am
REAL :: bm,Xm(2,2),Ym(3),sol1,sol2
TYPE(PARPASS1) :: PARAM1
TYPE(PARPASS2) :: PARAM2
am = 1
bm = 3.5
Xm(1,:) = [1.0, 2.0]
Xm(2,:) = [0.5, 2.5]
Ym(1:3) = [0.25,0.50,0.75]
PARAM1%a = am
PARAM1%X = Xm
PARAM2%b = bm
PARAM2%Y = Ym
CALL MYSUB(sol1,OBJ1,PARAM1)
CALL MYSUB(sol2,OBJ2,PARAM2)
PRINT *,sol1
PRINT *,sol2
CONTAINS
SUBROUTINE OBJ1(sumval,PARAM)
REAL,INTENT(OUT) :: sumval
TYPE(PARPASS1),INTENT(IN) :: PARAM
INTEGER :: a
REAL,ALLOCATABLE :: X(:,:)
a = PARAM%a
X = PARAM%X
sumval = a+X(1,1)+X(2,2)
END SUBROUTINE OBJ1
SUBROUTINE OBJ2(divval,PARAM)
REAL,INTENT(OUT) :: divval
TYPE(PARPASS2),INTENT(IN) :: PARAM
REAL :: b
REAL,ALLOCATABLE :: Y(:)
b = PARAM%b
Y = PARAM%Y
divval = b/(Y(1)+Y(2))
END SUBROUTINE OBJ2
END PROGRAM MAIN
和被叫mylib.90
MODULE MYLIB
USE MYPAR
IMPLICIT NONE
CONTAINS
SUBROUTINE MYSUB(sol,FN,PARAM)
REAL,INTENT(OUT) :: sol
TYPE(PARPASS1), INTENT(IN) :: PARAM
CALL FN(sol,PARAM)
sol = 2*sol
END SUBROUTINE MYSUB
END MODULE MYLIB
顯然模塊,如果我評論的線條與CALL MYSUB(sol2,OBJ2,PARAM2)
和PRINT *,sol2
,我的代碼運行順利。這是我以前有兩個「目標函數」,但現在當我有它們時,它不起作用,因爲MYSUB中的派生類型變量PARPASS1不能是任意的。
任何想法?
謝謝!這將解決當前的問題,但不幸的是,這不是一個通用的解決方案。如果有人需要撥打MYSUB 3次或更多次,該怎麼辦?複製和粘貼MYSUB的不同PARPASS類型的副本是沒有意義的,因爲擁有通用子程序(在我的理解中)的想法不需要修改它。沒有其他辦法可以解決這個問題嗎?它不應該使用派生數據類型,這只是我最初的方法。 – 2014-11-23 22:05:00
@ Lord_77我添加了一個應該更具擴展性的新解決方案 – Exascale 2014-11-24 07:47:31
只是一個側面問題。難道不能將類型名稱作爲子例程的輸入嗎?所以我們稱之爲MYSUB,我只需要輸入CALL MYSUB(sol1,'PARPASS1',PARAM1)。在這種情況下,'PARPASS1'可以是用於在MYSUB中聲明PARAM1類型的字符串。 @ kyle-g – 2014-11-24 17:54:01