在Fortran中正确实现显式接口 [英] Correct implementation of an explicit interface in Fortran
问题描述
我在Fortran的显式接口中苦苦挣扎.
I am struggling with explicit interfaces in Fortran.
在一个实例中,当我尝试使用假定形状的数组作为函数或子例程(即过程)的伪参数时,编译器已要求我编写一个显式接口:的显式接口...假定形状参数
.例如,它在子例程中看起来像 REAL,INTENT(IN OUT):: dummy_array(:)
.数组声明中的(:)
表示编译器负责将有关数组形状的信息传递给子例程.这很方便,但这也意味着编译器必须知道在编译调用或对该过程的引用时要执行此操作.仅从 CALL
(或引用)来看,这是不明显的,因此编译器必须具有有关该过程的伪参数的信息,因此需要显式接口.
In one instance, the compiler has requested that I write an explicit interface when I attempt to use an assumed-shape array as a dummy argument for a function or subroutine (i.e., procedure): Explicit interface required for ... assumed-shape argument
. For example, this would appear like REAL, INTENT(IN OUT) :: dummy_array(:)
in a subroutine. The (:)
in the declaration of the array means that the compiler takes care of passing information about the shape of the array to the subroutine. That's handy, but it also means that the compiler must know to do this when compiling the call or reference to the procedure. This is not evident from the CALL
(or reference) alone, so the compiler must have information about the procedure's dummy arguments, hence the need for a explicit interface.
据我了解,有三种方法可以在Fortran中实现显式接口:
From what I understand, there are three methods for implementing an explicit interface in Fortran:
- 使用一个
MODULE
对该程序进行CONTAINS
.这往往是推荐的方法. - 将过程 internal 设置为调用它的对象.这就像在主程序的
END
语句之前放置CONTAINS
语句一样.然后,我的过程的整个代码将放在这两个语句之间. - 为该过程编写一个
INTERFACE
.我想大多数人都默认使用此方法,但是它往往是最少推荐的方法,因为这可能会比较费力.
- Use a
MODULE
thatCONTAINS
the procedure. This tends to be the recommended approach. - Make the procedure internal to whatever calls it. This would be like putting a
CONTAINS
statement right before theEND
statement of my main program. The entire code of my procedure would then be placed between these two statements. - Write an
INTERFACE
for the procedure. I guess most folks default to this, but it tends to be the least recommended approach as it can be a bit laborious.
这使我想到了当前的问题:在另一个实例中,编译器给出了...可分配参数所需的 Explicit接口
.以下是上述方法1的相关部分:
This brings me to my current problem: In another instance, the compiler gives Explicit interface required for ... allocatable argument
. Here are the relevant parts following method 1 above:
MODULE My_Module
CONTAINS
SUBROUTINE Clean(my_array_sizes, my_arrays, my_arrays_clean)
USE Shared, ONLY : dp
IMPLICIT NONE
...
REAL(dp), INTENT(OUT), ALLOCATABLE, ASYNCHRONOUS :: my_arrays_clean(:)
...
ALLOCATE(my_arrays_clean(non_zero)) !new array of correct size
my_arrays_clean = temp(1:non_zero) !transfer values
END SUBROUTINE Clean
END MODULE My_Module
问题似乎出在虚拟数组 my_arrays_clean
上.这是电话:
The problem seems to be with the dummy array my_arrays_clean
. Here's the call:
CALL Clean(my_array_size, probability, probability_clean) !remove empty values from array
probability_clean
的声明:
REAL(dp), DIMENSION(:), ALLOCATABLE, ASYNCHRONOUS :: probability, probability_clean !store Photon(E_i, depth) values
一切似乎都很好,直到我尝试使用 gfortran -g -std = f2008 -Wall -Wextra -O2 -fall-intrinsics -fopenmp
进行编译:对"clean_"的未定义引用代码>.我不知道怎么了当然,我可以解决这个问题来完成我需要的工作,但我真的很想了解执行此操作的正确方法.
All seems well until I try to compile with gfortran -g -std=f2008 -Wall -Wextra -O2 -fall-intrinsics -fopenmp
: undefined reference to 'clean_'
. I have no idea what's wrong. Of course I can work around this problem to accomplish what I need, but I'd really like to understand the proper way to do this.
推荐答案
当我们谈论一个显式(或隐式)接口时,我们不是在谈论过程本身的属性.一个过程具有一个接口,但这不是完全相同的概念.如下所示,获取模块和子例程.
When we talk about an explicit (or implicit) interface, we aren't talking about a property of the procedure itself. A procedure has an interface, but this is not entirely the same concept. Take the module and subroutine as below.
module mod
contains
subroutine sub
end subroutine
end module
子例程 sub
具有一个接口,包括这样的信息,即它是一个名为 sub
的子例程,没有伪参数.问题中感兴趣的子例程具有其自己的对应接口.
The subroutine sub
has an interface, including such information as it being a subroutine called sub
with no dummy arguments. The subroutine of interest from the question has its own corresponding interface.
显式接口"代之以关于在引用过程的点上已知的有关过程接口的信息.看
The "explicit interface" instead is about what information is known about the procedure's interface at the point at which the procedure is referenced. Look at
call sub
end
并与
use mod, only : sub
call sub
end
在第一种情况下,在不使用模块 mod
的情况下,编译器甚至无法将 sub
视为模块内的子例程. sub
这里是带有隐式接口的外部过程(而不是模块中的那个).在第二个中, sub
是 use关联的;
In the first case, without using the module mod
the compiler can't even see sub
as being the subroutine within the module. sub
here is an external procedure with implicit interface (and not the one in the module). In the second, sub
is use associated; not only does the compiler now see the module subroutine but it sees the interface (which is now explicit).
同样,内部过程(使用 contains
语句的项目2)在其宿主中始终具有显式接口:
Likewise, an internal procedure (item 2. using the contains
statement) always has an explicit interface in its host:
call sub
contains
subroutine sub
end subroutine
end program
第三,带有接口块:
subroutine sub
end subroutine
interface
subroutine sub
end subroutine
end interface
call sub
end program
结论:可访问模块过程始终具有可用的显式接口,但是必须首先使用 use
语句使它们可访问.内部过程始终可以在主机中使用始终带有显式接口的方式进行访问.接口块提供了一个显式接口,但同样,接口块本身必须位于过程引用所在的位置.
In conclusion: accessible module procedures always have an explicit interface available, but they must first be made accessible with a use
statement. Internal procedures are always accessible in the host, always with an explicit interface. Interface blocks provide an explicit interface, but again the interface block itself must be around where the procedure reference is made.
这篇关于在Fortran中正确实现显式接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!