如何使用Fortran将数组传递给作为参数传递给另一个过程的过程
我试图将另一个子例程_b的名称和数组传递给通用子例程_a。该子例程_a应将数组传递给子例程_b并返回其计算值 以下是我编写的代码:如何使用Fortran将数组传递给作为参数传递给另一个过程的过程,fortran,Fortran,我试图将另一个子例程_b的名称和数组传递给通用子例程_a。该子例程_a应将数组传递给子例程_b并返回其计算值 以下是我编写的代码: module pass_subroutine_mod1 implicit none private public :: ave_value, fx contains subroutine ave_value( func, x, y, ave ) ! Calculate average of y
module pass_subroutine_mod1
implicit none
private
public :: ave_value, fx
contains
subroutine ave_value( func, x, y, ave )
! Calculate average of y which is passed on from another function `func`.
!
external :: func
double precision, intent(in), dimension(:) :: x
double precision, intent(inout), dimension(:) :: y
double precision, intent(inout) :: ave
integer :: n
N = size( x )
call func( x, y )
ave = sum( y ) / dble( N )
return
end subroutine ave_value
subroutine fx( x, y )
double precision, dimension(:), intent(in) :: x
double precision, dimension(:), intent(inout) :: y
y = x ** 3
return
end subroutine fx
end module pass_subroutine_mod1
program main
use :: pass_subroutine_mod1
implicit none
integer :: i, N = 101
double precision :: ave
double precision, allocatable, dimension(:) :: x, y
allocate( x(N), y(N), source=0.0d0 )
do i = 1, N
x(i) = dble( i - 1 )
end do
call ave_value( fx, x, y, ave )
write( *, '(A, ES15.6E3)' ) "Average value of y (from fx) = ", ave
deallocate( x, y )
end program main
这里ave\u value()
是子程序a,fx()
是子程序b
当我编译并运行上述代码时,它抛出以下错误:
At line 28 of file pass_subroutine.f90
Fortran runtime error: Array bound mismatch for dimension 1 of array 'y' (1/1125899906842625)
第28行是子例程fx(x,y)
中的y=x**3
行。
因此,数组x
和y
似乎没有正确地传递到fx()
,因为当我试图从fx()
内打印x
时,它无法这样做
如果使用标量(并相应地更新代码)而不是数组x
和y
,则代码能够正常运行并输出所需的结果
此外,在完成之后,如果通过添加接口块修改ave_值
,代码将再次正常运行。以下是使用平均值进行的修改:
subroutine ave_value( func, x, y, ave )
! Calculate average of y which is passed on from another function `func`.
!
external :: func
double precision, intent(in), dimension(:) :: x
double precision, intent(inout), dimension(:) :: y
double precision, intent(inout) :: ave
integer :: n
interface
subroutine func( ip, op )
double precision, dimension(:), intent(in) :: ip
double precision, dimension(:), intent(inout) :: op
end subroutine func
end interface
N = size( x )
call func( x, y )
ave = sum( y ) / dble( N )
return
end subroutine ave_value
因此,我的问题是:
a) 上述修改是否正确
b) 如果是,那么为什么在处理数组时需要接口块而在处理标量时不需要接口块?需要显式接口的是假定的形状数组伪参数维度(:)
。这是因为编译器必须对它们执行不同的操作,通常传递一个描述符。调用端的内容并不重要,重要的是被调用过程的伪参数
有关更多信息,请参阅我以前的博客文章
您可能需要查看语言功能抽象接口
,以及过程
,以使代码看起来更干净。当您有一个伪过程参数时,正如ave_value
中的func
一样,没有“假定接口”。虽然数组伪参数x
和y
是假定的形状(它们的形状来自调用过程时的实际参数),但过程没有类似的情况
相反,过程func
具有声明它的接口。在这种情况下,您拥有声明
external :: func
因此func
是一个具有隐式接口的外部过程。正如我们所知,隐式接口在我们想要引用它时是不合适的,并且它假定了形状数组参数ip
和op
您需要以某种方式显式地为伪参数提供正确的接口。如您所见,一种方法是使用接口块为外部过程提供显式接口。或者,您可以使用过程声明语句,如
procedure(iface) func
其中,iface
是一个合适的接口。有几种方法可以使该界面可用,但我在这里不赘述。Darn-我知道区别,但一直说错话。编辑-谢谢。谢谢你的回答。我认为将过程放在模块中会自动为它提供一个明确的接口。我这样想的另一个原因是,如果我将call func(x,y)
行替换为call fx(x,y)
,而不是通过名称func
调用fx
,则代码可以在没有接口块的情况下工作。当fx
位于不同的模块中时,它显然不起作用,这两种情况之间有什么区别?即使您调用的过程位于可见的模块中,当您将过程作为参数传递时,也没有什么可以将“外部函数”与该过程联系起来。这就是func必须有一个显式接口的原因。谢谢。当我将假定的shape数组参数更改为假定的大小时,代码将正确运行,而不使用接口块。此外,我尝试将fx
子例程编写为C代码,并从fortran模块调用它。即使这样,我也不需要接口块。因此,问题似乎在于在外部过程中使用假定的形状数组(您和Steve都提到过,但我稍微改变了措辞)!再次感谢。是的,这就是为什么你需要一个显式接口的关键所在——但是如果用C编写的fx
有一个C-可互操作的接口,那么它也需要这个显式接口。我的答案不是为什么需要显式接口,而是为什么该接口不能用于伪过程参数。