将函数传递给子例程时,虚拟过程'f'中的接口不匹配

时间:2013-04-10 13:07:21

标签: fortran fortran90

我正在尝试编写一个有两个参数的子程序(用于最小化):

  • 任意长度的数组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,它也可以正常工作。但这些解决方案都没有让我得到我想要的东西。

关于如何实现这一目标的任何想法?

4 个答案:

答案 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