Correct implementation of an explicit interface in Fortran

与世无争的帅哥 提交于 2021-02-05 09:30:10

问题


I am struggling with explicit interfaces in Fortran.

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.

From what I understand, there are three methods for implementing an explicit interface in Fortran:

  1. Use a MODULE that CONTAINS the procedure. This tends to be the recommended approach.
  2. Make the procedure internal to whatever calls it. This would be like putting a CONTAINS statement right before the END statement of my main program. The entire code of my procedure would then be placed between these two statements.
  3. 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.

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

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

The declaration of probability_clean:

  REAL(dp), DIMENSION(:), ALLOCATABLE, ASYNCHRONOUS :: probability, probability_clean !store Photon(E_i, depth) values

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.


回答1:


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

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

and compare it with

use mod, only : sub
call sub
end

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).

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

Third, with an interface block:

subroutine sub
end subroutine

  interface
    subroutine sub
    end subroutine
  end interface

  call sub
end program

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.



来源:https://stackoverflow.com/questions/55270873/correct-implementation-of-an-explicit-interface-in-fortran

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!