我正在尝试编写一个用于最小化的通用子例程。因为我想有一个通用的子程序,所以目标函数可以有不同的参数,不仅在名称中,而且在维度中也是如此。所以我需要一种方法来传递参数结构(我使用的是单词结构,因为我的想法是使用类似于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