2

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

  • 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

4 回答 4

5

怎么样:

interface
  real pure function f(y)
    real, dimension(:), intent(in) :: y
  end function
end interface

当您将参数传递solve给函数时,将自动传递数组的大小。您不需要制作界面的这一部分。

于 2013-04-10T13:18:08.957 回答
2

如果您想获得MSB解决方案评论中所示的安全性,您应该使用-fcheck=bounds并且编译器将为假定和延迟形状数组生成运行时检查。有关更多信息,请参见 gfortran 手册页-fcheck。但是,您会损失一些速度。

于 2013-04-11T10:08:21.817 回答
1

您有解决方案,但值得解释的是......如果虚拟参数具有显式接口(它在此处执行),则要求作为实际参数传递的过程的特征必须与虚拟参数,除了一些关于纯粹性和基本内在函数的例外。除其他外,过程的特征包括其虚拟参数的特征。

虚拟参数的特征包括其形状等。如果该形状不是常量表达式 - 特征包括“[形状] 对表达式中实体的确切依赖性”。

dummy 参数的接口块f将数组声明为 size SIZE(x)。x 是与主机相关的假定形状变量 - 它的大小可以在运行时变化,因此SIZE(x)不是常数。因此,该表达式及其中的实体成为虚拟参数的特征。

模块过程g将数组声明为 size 2。这显然是一个常数。

无论 f 的虚拟参数大小的非常量表达式的值如何,这些数组大小特征(某种表达式与常量)都不匹配 - 因此出现错误。

当您SIZE(x)用常数 2 替换时,特征显然匹配。当您将假定的形状更改x为常量大小 2 - 然后SIZE(x)变为值 2 的常量表达式 - 因为它是一个常量表达式,所有相关的是它的值 - 因此两个参数的特征然后匹配。当您将 的虚拟参数f和 的虚拟参数都g更改为假设 shape(:)时,特征匹配。

于 2013-04-10T20:46:04.020 回答
0

这是一个演示如何传递可分配数组。

一些技巧:

  • 使用模块避免繁琐的界面。
  • 将数组传递给实际函数时添加额外的矩阵大小信息。例如f(y, sizeinfo),在您的实际函数中,您可以正确声明输入矩阵的大小。可分配数组可以传递给 subroutine solve,因此可以在 subroutine 中使用 size(mat) 获得大小solve

所以一个更正的版本看起来像:

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 
于 2017-02-21T01:23:41.610 回答