问题
I am trying to write a subroutine (for minimisation) that has two arguments:
- an array
x
of any length - a function
f
that takes an array of that length and returns a scalar
example module:
module foo
contains
subroutine solve(x, f)
real, dimension(:), intent(inout) :: x
interface
real pure function f(y)
import x
real, dimension(size(x)), intent(in) :: y
end function
end interface
print *, x
print *, f(x)
end subroutine
end module
and test program:
use foo
real, dimension(2) :: x = [1.0, 2.0]
call solve(x, g)
contains
real pure function g(y)
real, dimension(2), intent(in) :: y
g = sum(y)
end function
end
gfortran fails on:
call solve(x, g)
1
Error: Interface mismatch in dummy procedure 'f' at (1): Shape mismatch in dimension 1 of argument 'y'
If I change size(x) => 2
then it compiles (and runs) fine. It also works fine if I change : => 2
. But neither of these solutions gets me what I want.
Any ideas on how I can achieve this?
回答1:
How about:
interface
real pure function f(y)
real, dimension(:), intent(in) :: y
end function
end interface
When you pass the argument of solve
to the function, the size of the array will automatically be passed. You don't need to make this part of the interface.
回答2:
If you want to gain safety as indicated in your comment of M.S.B's solution, you should use -fcheck=bounds
and the compiler will generate run-time checks for assumed and deferred shape arrays. See the gfortran man page for more info on -fcheck
. However, you will lose some speed.
回答3:
You have the solution, but for what its worth an explanation... if the dummy argument has an explicit interface (which it does here) then there is a requirement that the characteristics of a procedure passed as an actual argument must match those of the dummy argument, with some exceptions around pureness and elemental intrinsics. The characteristics of a procedure include the characteristics of its dummy arguments, amongst other things.
The characteristics of a dummy argument include its shape, amongst other things. If that shape is not a constant expression - the characteristics include "the exact dependence [of the shape] on the entities in the expression".
The interface block for the dummy argument f
declares the array to be of size SIZE(x)
. x is a host associated assumed shape variable - its size can vary at runtime, so SIZE(x)
is not a constant. Hence that expression and the entities in it becomes a characteristic of the dummy argument.
The module procedure g
declares the array to be of size 2
. That is clearly a constant.
Regardless of the value of the non-constant expression for the size of the dummy argument of f, those array size characteristics (some sort of expression vs a constant) don't match - hence the error.
When you replace SIZE(x)
with the constant 2 the characteristics obviously match. When you change the assumed shape x
to be a constant size 2 - then SIZE(x)
becomes a constant expression of value 2 - because it is a constant expression all that is relevant is its value - hence the characteristics of the two arguments then match. When you change both the dummy argument of f
and the dummy argument of g
to be assumed shape (:)
, the characteristics match.
回答4:
Here is a demo to show how to pass allocatable array.
Some tips:
- Use modules to avoid cumbersome interface.
- Add extra matrix size information when pass array to the actual function. For example
f(y, sizeinfo)
so that inside your actual function you can declare the size of the input matrix correctly. The allocatable array can be passed to subroutinesolve
, so the size can be obtained using size(mat) in your subroutinesolve
.
So a corrected version looks like:
module foo
contains
subroutine solve(x, f)
real, dimension(:), intent(inout) :: x
real,external::f
integer::sizeinfo
print *,'x=', x
sizeinfo = size(x)
print *, 'f(x)=',f(x,sizeinfo)
end subroutine
real function g(y,sizeinfo)
integer::sizeinfo
real, dimension(sizeinfo) :: y
g = sum(y)
end function
end module
Here is main program:
program main
use foo
real, dimension(2) :: x = (/1.0, 2.0/)
call solve(x, g)
end program
And the result is :
x= 1.000000 2.000000
f(x)= 3.000000
来源:https://stackoverflow.com/questions/15926727/interface-mismatch-in-dummy-procedure-f-when-passing-a-function-to-a-subroutin