【问题标题】:Fortran - explicit interfaceFortran - 显式接口
【发布时间】:2013-05-05 09:46:40
【问题描述】:

我对 Fortran 很陌生,为了我的研究,我需要运行一个模型怪物,所以我边走边学。所以如果我问一个“愚蠢”的问题,我很抱歉。 我正在尝试编译(Mac OSX,从命令行)并且我已经设法解决了一些问题,但是现在我遇到了一些我不确定如何解决的问题。我想我明白了错误背后的想法,但同样不知道如何解决。

模型很大,所以我只会发布我认为相关的代码部分(尽管我可能是错的)。我有一个包含几个子例程的文件,开头为:

    !==========================================================================================!
!    This subroutine simply updates the budget variables.                                  !
!------------------------------------------------------------------------------------------!
subroutine update_budget(csite,lsl,ipaa,ipaz)

   use ed_state_vars, only : sitetype     ! ! structure
   implicit none

   !----- Arguments -----------------------------------------------------------------------!
   type(sitetype)  , target     :: csite
   integer         , intent(in) :: lsl
   integer         , intent(in) :: ipaa
   integer         , intent(in) :: ipaz
   !----- Local variables. ----------------------------------------------------------------!
   integer                      :: ipa
   !----- External functions. -------------------------------------------------------------!
   real            , external   :: compute_water_storage
   real            , external   :: compute_energy_storage
   real            , external   :: compute_co2_storage
   !---------------------------------------------------------------------------------------!


   do ipa=ipaa,ipaz
      !------------------------------------------------------------------------------------!
      !      Computing the storage terms for CO2, energy, and water budgets.               !
      !------------------------------------------------------------------------------------!
      csite%co2budget_initialstorage(ipa) = compute_co2_storage(csite,ipa)
      csite%wbudget_initialstorage(ipa)   = compute_water_storage(csite,lsl,ipa)
      csite%ebudget_initialstorage(ipa)   = compute_energy_storage(csite,lsl,ipa)
   end do

   return
end subroutine update_budget
!==========================================================================================!
!==========================================================================================!

我收到错误消息

budget_utils.f90:20.54:

真实的,外部的 :: compute_co2_storage 1
错误:(1) 处的过程“compute_co2_storage”的虚拟参数“csite”具有需要此过程的显式接口的属性

(我得到了一堆,但它们基本上都是一样的)。现在,查看 ed_state_vars.f90(在子例程中“使用”),我发现

!============================================================================!
!============================================================================!
  !---------------------------------------------------------------------------!  
  ! Site type:
  ! The following are the patch level arrays that populate the current site.
  !---------------------------------------------------------------------------!  

type sitetype


     integer :: npatches

     !  The global index of the first cohort in all patches
     integer,pointer,dimension(:) :: paco_id

     ! The number of cohorts in each patch
     integer,pointer,dimension(:) :: paco_n

     ! Global index of the first patch in this vector, across all patches
     ! on the grid

     integer :: paglob_id

     ! The patches containing the cohort arrays
     type(patchtype),pointer,dimension(:) :: patch

等等 - 这需要另外 500 行左右。 因此,为了能够使用(虚拟)参数 csite,原始子例程似乎需要为其过程提供显式接口。同样,我对 Fortran 很陌生,但我真的很想了解它是如何“思考”的。我一直在寻找拥有显式接口的含义,何时(以及如何!)使用它等。但我无法弄清楚它在我的案例中是如何应用的。我是否应该使用不同的编译器(英特尔?)。有什么提示吗?

编辑:所以csite 在所有过程中都被声明为target,并且声明type(site type) 包含一大堆pointers,如sitetype 中所指定。但是 sitetype 在所有过程中都来自另一个模块 (ed_state_vars.f90) 的 used。所以我仍然很困惑为什么它会给我显式接口错误?

【问题讨论】:

  • 你的模块中有compute_water_storage和其他函数吗?
  • 我们需要在compute_co2_storage() 中查看csite 的声明,因为错误消息指的是该例程中声明的属性,而不是update_budget() 中的属性。我怀疑它被声明为 OPTIONALPOINTER 或类似的东西。
  • 感谢所有反馈。 @SethMMorton:是的,就像real function。 @Deditos:在compute_co2_storage() 中,csite 的声明与我发布的子例程中的相同:type(sitetype) , target :: csite
  • @Geraldine 曾经解决过这个问题吗?有同样的问题
  • @badgley 我想最后可能是我的编译器或 MPI 或 makefile 中的某些设置有问题。我最终与我们大学高性能计算机中心的人一起工作,他们让它运行没有问题......

标签: compilation fortran explicit-interface


【解决方案1】:

“显式接口”表示向编译器声明过程(子例程或函数)的接口。这允许编译器检查对过程的调用与实际过程之间的参数的一致性。这样可以发现很多程序员的错误。您可以使用interface 语句写出接口,但有一个更简单的方法:将过程放入一个模块中,然后use 该模块来自调用它的任何其他实体——来自主程序或任何过程那本身不在模块中。但是您不会 use 来自同一模块中另一个过程的过程 - 它们是自动相互认识的。

将过程放入模块中会自动使其接口为编译器所知,并可在useed 时进行交叉检查。这比编写界面更容易,也更不容易出错。使用接口,您必须复制过程参数列表。那么如果你修改了程序,你也必须修改调用(当然!)还有接口。

当您使用“高级”参数时,需要显式接口(@98​​7654325@ 语句或模块)。否则编译器不知道生成正确的调用

如果你有一个useed 的过程,你不应该用external 来描述它。在现代 Fortran 中很少使用 external —— 所以,删除 external 属性,将所有过程放入一个模块中,然后 use 它们。

【讨论】:

  • 不过,将一百万行模型转换为模块可能非常困难。
  • 我明白你在说什么(很好的解释,谢谢!)。并且被调用的过程是文件中的real functions,所以我猜它们甚至不必声明为external?或者,由于它们并非都专门捆绑为一个模块,它们仍然应该? (因为是的,正如@Vladimir 所说,这是一个太大的模型,无法将所有内容都转换为模块......)。 real functions 使用来自另一个文件的信息(请参阅我对原始问题的编辑),但他们使用use(获取sitetype,用于声明csite)。
【解决方案2】:

我在我的 mac 10.9 上尝试安装 ED2 时遇到了同样的问题。我通过在一个模块中包含该文件中的所有子例程来修复它,即:

module mymodule
contains
subroutine update_budget(csite,lsl,ipaa,ipaz)
other subroutines ecc.
end module mymodule

必须对包中的大约 10 到 15 个其他文件执行相同的操作。 我已经编译了所有文件并生成了相应的目标文件,但现在我收到有关未定义符号的错误。但是我怀疑这些与修改无关,所以如果有人有耐心,这可能是至少解决接口问题的一种方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-12
    • 2018-09-14
    • 1970-01-01
    • 2013-09-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多