isyegatech
Technical User
I am starting this thread to ask for help solve a problem that might come from my wrong specification of a function interface, but I don't know how to fix it.
The error message I encountered is short and simply says, "Illegal number or type of arguments to lnsrch - arguments of fmin and func do not agree."
The definition of LNSRCH, FMIN, and FUNC will be clear in the content below.
The original program code is trimmed to illustrate my intention as the following (which consists of three parts: a main program unit called MAIN, a module named MODEL, and a module named NEWTON). You should be able to reproduce the error message just putting these three program units together.
Module MODEL just defines a simple equations system in two variables---y(1)=x(1); y(2)=x(2) ---in the subprogram FUNC_SYSTEM1. Module MODEL also contains an abstract interface for future extension so that I can simply make the pointer FUNCV to reference any other equation system of the same kind as the current example equation system FUNC_SYSTEM1, with the exception only in the number of variables of the equation system.
Module NEWTON defines the relationship among three subprograms that are key to the program's computing: BROYDEN will call FMIN to get the sum of squares of x(1) and x(2); simultaneously, in FMIN, the vector of x(1) and x(2) is assigned to an array pointer called FMIN_FVECP. This array pointer is to be used to do some side calculation in the function LNSRCH.
The main program unit is defined as follows:
Sorry for the lengthy post. Thanks for the time reading through my question. Looking forward to any input for working around the error message. Thanks.
Lee
The error message I encountered is short and simply says, "Illegal number or type of arguments to lnsrch - arguments of fmin and func do not agree."
The definition of LNSRCH, FMIN, and FUNC will be clear in the content below.
The original program code is trimmed to illustrate my intention as the following (which consists of three parts: a main program unit called MAIN, a module named MODEL, and a module named NEWTON). You should be able to reproduce the error message just putting these three program units together.
Module MODEL just defines a simple equations system in two variables---y(1)=x(1); y(2)=x(2) ---in the subprogram FUNC_SYSTEM1. Module MODEL also contains an abstract interface for future extension so that I can simply make the pointer FUNCV to reference any other equation system of the same kind as the current example equation system FUNC_SYSTEM1, with the exception only in the number of variables of the equation system.
Code:
MODULE model
IMPLICIT NONE
REAL, DIMENSION(:), POINTER :: fmin_fvecp
ABSTRACT INTERFACE
FUNCTION function_system_template(x) RESULT(y)
REAL, DIMENSION(:), INTENT(IN) :: x
REAL, DIMENSION(SIZE(x)) :: y
END FUNCTION
END INTERFACE
PROCEDURE(function_system_template), POINTER :: funcv
CONTAINS
FUNCTION func_system1(x) Result(y)
IMPLICIT NONE
REAL, DIMENSION(:), INTENT(IN) :: x
REAL, DIMENSION(size(x)) :: y
y(1)=x(1)
y(2)=x(2)
END FUNCTION func_system1
END MODULE model
Code:
MODULE newton
USE model
IMPLICIT NONE
REAL, DIMENSION(:), POINTER :: fmin_fvecp
CONTAINS
SUBROUTINE broyden(x,fmin_fvecp,funcv)
IMPLICIT NONE
REAL, DIMENSION(:), INTENT(IN) :: x
REAL, DIMENSION(size(x)), TARGET :: y
REAL, DIMENSION(:), POINTER :: fmin_fvecp
PROCEDURE(function_system_template), POINTER :: funcv
fmin_fvecp=>y
print*,fmin(x,fmin_fvecp,funcv) ! Get the sum of squares
print*,fmin_fvecp ! Show the vector x(1) and x(2)
print*,lnsrch(x,fmin,fmin_fvecp,funcv) ! Show the figure calculated in LNSRCH
END SUBROUTINE broyden
FUNCTION fmin(x,fmin_fvecp,funcv) RESULT(y)
IMPLICIT NONE
REAL, DIMENSION(:), INTENT(IN) :: x
REAL, DIMENSION(:), POINTER :: fmin_fvecp
PROCEDURE(function_system_template), POINTER :: funcv
REAL :: y
fmin_fvecp=funcv(x) ! The value of FMIN_FVECP is assigend
fmin=dot_product(fmin_fvecp,fmin_fvecp)! when FMIN is called by BROYDEN
END FUNCTION fmin
FUNCTION lnsrch(x,func,a_fvecp,b_funcv) RESULT(y)
IMPLICIT NONE
REAL, DIMENSION(:), INTENT(IN) :: x
REAL, DIMENSION(:), POINTER :: a_fvecp
PROCEDURE(function_system_template), POINTER :: b_funcv
INTERFACE
FUNCTION func(x,fvecp,funcp)
IMPLICIT NONE
REAL, DIMENSION(:), INTENT(IN) :: x
REAL :: func
REAL, DIMENSION(:), POINTER :: fvecp
PROCEDURE(function_system_template), POINTER :: funcp
END FUNCTION
END INTERFACE
REAL, DIMENSION(SIZE(x)) :: y
y=x+a_fvecp+b_funcv(x)+1000.
END FUNCTION lnsrch
END MODULE newton
Code:
PROGRAM main
USE model
USE newton
IMPLICIT NONE
REAL, DIMENSION(:), allocatable :: x
allocate(x(2))
x=[1.,2.] ! The input arguments to be passed into
funcv=>func_system1 ! the equation system, FUNC_SYSTEM1.
call broyden(x,fmin_fvecp,funcv) ! Call BROYDEN to do the subsequent calcualtion
deallocate(x)
END PROGRAM main
Lee