如何使用Fortran将数组传递给一个过程,该过程作为参数传递给另一个过程 [英] How to pass array to a procedure which is passed as an argument to another procedure using Fortran
问题描述
我试图将另一个subroutine_b的名称和一个数组传递给泛型subroutine_a.该subroutine_a应该将数组传递给subroutine_b并取回其计算值.
以下是我编写的代码:
模块pass_subroutine_mod1隐式无私人的公共:: ave_value,fx包含子程序ave_value(func,x,y,ave)!计算从另一个函数func传递的y的平均值.!外部:: func双精度,意图(in),尺寸(:) :: x双精度,意图(输入),尺寸(:) :: y双精度,intent(inout):: ave整数:: nN =尺寸(x)调用func(x,y)ave = sum(y)/dble(N)返回结束子程序ave_value子程序fx(x,y)双精度,尺寸(:),意向(in):: x双精度,尺寸(:),意图(进出):: yy = x ** 3返回结束子程序fx终端模块pass_subroutine_mod1程序主体使用:: pass_subroutine_mod1隐式无整数:: i,N = 101双精度:: AVE双精度,可分配,尺寸(:) :: x,y分配(x(N),y(N),source = 0.0d0)我= 1,Nx(i)= dble(i-1)做完调用ave_value(fx,x,y,ave)write(*,'(A,ES15.6E3)')"y的平均值(来自fx)=",ave解除分配(x,y)结束程序主要
此处 ave_value()
是子例程a,而 fx()
是子例程_b.
当我编译并运行上面的代码时,它将引发以下错误:
在pass_subroutine.f90文件的第28行Fortran运行时错误:数组'y'的维度1的数组绑定不匹配(1/1125899906842625)
第28行
是子例程 fx(x,y)
中的第 y = x ** 3
行.因此,似乎数组 x
和 y
没有正确地传递给 fx()
,因为当我尝试打印 x 中的
fx()
中的code>,则无法执行此操作.
如果我使用标量(并相应地更新代码)而不是数组 x
和 y
,则代码能够正常运行并输出所需的结果./p>
此外,经过解决方案
假定形状数组伪参数 dimension(:)
需要显式接口.这是因为编译器必须为此做一些不同的事情,通常会传递一个描述符.无关紧要的是什么,重要的是被调用过程的伪参数.
有关更多信息,请参阅我的旧博客文章 Fortran医生再次获得了明确的权限!
您可能希望查看语言功能抽象界面
和 procedure
,以使代码看起来更简洁.
I am trying to pass the name of another subroutine_b and an array to a generic subroutine_a. This subroutine_a is supposed to pass the array to subroutine_b and get back its computed value.
Following is the code that I have written:
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
Here ave_value()
is the subroutine_a and fx()
is subroutine_b.
When I compile and run the above code, it throws the following error:
At line 28 of file pass_subroutine.f90
Fortran runtime error: Array bound mismatch for dimension 1 of array 'y' (1/1125899906842625)
Line 28
is the line y = x ** 3
in subroutine fx( x, y )
.
It thus seems that the arrays x
and y
are not properly passed to fx()
because when I try to print x
from within fx()
, it is unable to do so.
If, instead of arrays x
and y
, I use scalars (and update the code accordingly) the code is able to run properly and output the desired result.
Additionally, after going through this thread, if I modify the ave_value
by adding an interface block, the code runs properly again. Following is the modification with ave_value
:
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
Thus, my questions are:
a) Is the above modification correct?
b) If yes, then why do I need an interface block when working with arrays and not when working with scalars?
It's the assumed-shape array dummy arguments dimension(:)
that require an explicit interface. This is because the compiler has to do something different for these, typically passing a descriptor. It doesn't matter what's on the calling side, it's the dummy arguments of the called procedure that matter.
For more information see my old blog post Doctor Fortran Gets Explicit - Again!
You may want to look at the language feature abstract interface
, along with procedure
, to make the code look a bit cleaner.
这篇关于如何使用Fortran将数组传递给一个过程,该过程作为参数传递给另一个过程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!