Silverfrost Forums

Welcome to our forums

Interface for subroutine passed with assumed shape argument?

13 Aug 2008 9:14 #3695

Dear People,

My question can be distilled to this specific example. I need to write the interface for a subroutine that calculates the gradient of an arbitrary scalar function of a vector argument x. This should work in general for a function of 2 variables , 3 variables, etc. Thus, I am tempted to use an assumed shape for position argument x in the interface. In other words, I want to avoid having to put a specific dimension of argument x to the function being passed - otherwise the subroutine is not general for any dimension of space. The following attempts do not work, but I don't know why. I looked in the corresponding sections of Metcalf and two other books, but they do not cover this. Any comments will be gratefully received.

With many thanks, Ludwig

PS: The colon in the assumed shape is being turned into an emiticon, but you get the idea.

FIRST EXAMPLE (pass function as argument)

subroutine gradient (func,x,g) real, dimension(:), intent(in) :: x real, dimension(size(x)), intent(out) :: g interface function func (y) result (f) real, dimension(:), intent(in) :: y real :: f end function func end interface ... end subroutine gradient

SECOND EXAMPLE (pass function as argument)

subroutine gradient (func,x,g) real, dimension(:), intent(in) :: x real, dimension(size(x)), intent(out) :: g interface function func (y) result (f) real, dimension(size(x)), intent(in) :: y real :: f end function func end interface ... end subroutine gradient

THIRD EXAMPLE (pass subroutine as argument)

subroutine gradient (sbr,x,g) real, dimension(:), intent(in) :: x real, dimension(size(x)), intent(out) :: g interface subroutine sbr (y,f) real, dimension(:), intent(in) :: y real, intent(out) :: f end subroutine sbr end interface ... end subroutine gradient

13 Aug 2008 10:22 #3696

The following appears to work provided that you don't use CHECKMATE

subroutine gradient (func,x,g) 
real, dimension(:), intent(in) :: x 
real, dimension(size(x)), intent(out) :: g 
interface 
function func(y) result(f) 
real, dimension(:),intent(in) :: y 
real :: f 
end function func
end interface
g = func(x) 
end subroutine gradient

function func(y) result(f) 
real, dimension(:),intent(in) :: y 
real :: f
f = sum(y) 
end function func

program main
interface 
subroutine gradient(func,x,g)
real, dimension(:), intent(in) :: x 
real, dimension(size(x)), intent(out) :: g 
interface 
function func(y) result(f) 
real, dimension(:),intent(in) :: y 
real :: f 
end function func
end interface
end subroutine gradient
end interface
interface 
function func(y) result(f) 
real, dimension(:),intent(in) :: y 
real :: f 
end function func
end interface
real xx(10),gg(10)
xx = 42.0
call gradient(func,xx,gg)
print*, gg
end program main
15 Aug 2008 2:31 #3703

Dear Paul,

Yes, yours is the solution. I have now tried this out and the code works.

It does mean that I each function must accept an assumed shape argument, even when the mathematical argument is a (/ x,y /) or (/ x,y,z /), etc. But that is really no problem.

With profuse thanks, Ludwig

Please login to reply.