我正在尝试编写一个有两个参数的子程序(用于最小化):
x
f
,它接受该长度的数组并返回一个标量示例模块:
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
和测试程序:
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失败了:
call solve(x, g)
1
Error: Interface mismatch in dummy procedure 'f' at (1): Shape mismatch in dimension 1 of argument 'y'
如果我改变size(x) => 2
,那么它编译(并运行)就好了。如果我更改: => 2
,它也可以正常工作。但这些解决方案都没有让我得到我想要的东西。
关于如何实现这一目标的任何想法?
答案 0 :(得分:5)
怎么样:
interface
real pure function f(y)
real, dimension(:), intent(in) :: y
end function
end interface
当您将solve
的参数传递给函数时,将自动传递数组的大小。您不需要创建界面的这一部分。
答案 1 :(得分:2)
如果您希望获得M.S.B解决方案评论中指出的安全性,则应使用-fcheck=bounds
,编译器将为假定和延迟形状数组生成运行时检查。有关-fcheck
的更多信息,请参阅gfortran手册页。但是,你会失去一些速度。
答案 2 :(得分:1)
你有解决方案,但是它值得解释...如果伪参数有一个显式接口(它在这里做),那么需要一个过程的特征作为实际参数传递的必须与伪参数的参数匹配,在纯粹性和元素内在函数方面有一些例外。程序的特征包括其伪参数的特征等等。
伪论证的特征包括其形状等。如果该形状不是常量表达式 - 特征包括“[形状]对表达式中实体的确切依赖性”。
伪参数f
的接口块声明数组大小为SIZE(x)
。 x是主机关联的假定形状变量 - 其大小可以在运行时变化,因此SIZE(x)
不是常量。因此,表达式及其中的实体成为伪参数的特征。
模块过程g
声明数组的大小为2
。这显然是一个常数。
无论f的伪参数大小的非常量表达式的值如何,那些数组大小特征(某种表达式与常量)不匹配 - 因此错误。
当您使用常量2替换SIZE(x)
时,特征明显匹配。当您将假定的形状x
更改为常量大小2时 - SIZE(x)
成为值2的常量表达式 - 因为它是一个常量表达式,所有相关的是它的值 - 因此它的特征然后两个参数匹配。当您将f
的伪参数和g
的伪参数更改为假定形状(:)
时,特征匹配。
答案 3 :(得分:0)
这是一个显示如何传递可分配数组的demo。
一些提示:
f(y, sizeinfo)
,这样在实际函数中你可以正确地声明输入矩阵的大小。可分配数组可以传递给子例程solve
,因此可以使用子例程solve
中的size(mat)来获取大小。因此修正后的版本如下:
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
这是主程序:
program main
use foo
real, dimension(2) :: x = (/1.0, 2.0/)
call solve(x, g)
end program
结果是:
x= 1.000000 2.000000
f(x)= 3.000000