你如何使用Fortran 90模块数据

时间:2009-08-06 18:06:03

标签: module fortran conventions fortran90

假设您有一个包含 lot 变量,函数和子例程的Fortran 90模块。在您的USE声明中,您遵循哪种惯例:

  1. 使用, only :语法明确声明您正在使用哪些变量/函数/子例程,例如USE [module_name], only : variable1, variable2, ...
  2. 插入一条毯子USE [module_name]
  3. 一方面,only子句使代码更加冗长。但是,它会强迫您在代码中重复自己,如果您的模块包含 lot 变量/函数/子例程,那么事情就会变得难以驾驭。

    以下是一个例子:

    module constants
      implicit none
      real, parameter :: PI=3.14
      real, parameter :: E=2.71828183
      integer, parameter :: answer=42
      real, parameter :: earthRadiusMeters=6.38e6
    end module constants
    
    program test
    ! Option #1:  blanket "use constants"
    !  use constants
    ! Option #2:  Specify EACH variable you wish to use.
      use constants, only : PI,E,answer,earthRadiusMeters
      implicit none
    
      write(6,*) "Hello world.  Here are some constants:"
      write(6,*) PI, &
           E, &
           answer, &
           earthRadiusInMeters
    end program test
    

    更新 希望有人说像“Fortran?只是用C#重新编码!”所以我可以投票给你。


    更新

    我喜欢Tim Whitcomb's answer,它将Fortran的USE modulename与Python的from modulename import *进行比较。以前在Stack Overflow上的主题:

    • ‘import module’ or ‘from module import’

      • In an answer,Mark Roddy提到:
          

        不要使用'from module import *'。对于   任何合理的大量代码,如果   你'导入''你的意志很可能   将其粘合到模块中,无法进行   即将被删除。这是因为它是   很难确定使用了哪些物品   在代码中来自'模块',   让它向东走到尽头   你认为你不使用的地方   进口,但它非常   很难确定。

    • What are good rules of thumb for python imports?

      • dbr's answer包含
          

        不要从x import * - 它做   你的代码很难理解,如   你不能轻易看到一个方法   来自(来自x import *;来自y   进口*; my_func() - 其中是my_func   定义?)

    所以,我倾向于达成共识,通过

    明确说明我在模块中使用的所有项目
    USE modulename, only : var1, var2, ...
    

    Stefano Borini mentions一样,

      

    [if]你有一个如此之大的模块   感觉被迫只添加,这意味着   你的模块太大了。拆分它。

7 个答案:

答案 0 :(得分:24)

我曾经只做use modulename - 然后,随着我的应用程序的增长,我发现找到函数的源代码越来越困难(没有转向grep) - 其他一些代码浮动在办公室周围仍然使用每个文件的一个子程序,它有自己的一组问题,但它使得使用文本编辑器更容易地浏览代码并快速找到你需要的东西。

在遇到这种情况后,我会尽可能地转换为使用use ... only。我也开始选择Python,并以与from modulename import *相同的方式查看它。模块为您提供了很多很棒的东西,但我更喜欢严格控制我的全局命名空间。

答案 1 :(得分:15)

这是一个平衡问题。

如果您只使用模块中的一些内容,那么只有添加才有意义,以明确指出您正在使用的内容。

如果你使用模块中的很多东西,那么只指定很多东西,所以它没有多大意义。你基本上是在挑选你使用的东西,但事实是你完全依赖于那个模块。

然而,最后一个最好的理念是:如果你担心名称空间污染,并且你有一个如此大的模块,你觉得有必要加入,那就意味着你的模块太大了。拆分它。

更新:Fortran?只是在python中重新编码;)

答案 2 :(得分:6)

这里没有完全回答这个问题,只是抛出我在某些情况下发现有用的另一个解决方案,如果由于某种原因您不想拆分模块并开始获取命名空间冲突。您可以使用派生类型在一个模块中存储多个名称空间。

如果存在一些变量的逻辑分组,您可以为每个组创建自己的派生类型,在模块中存储此类型的实例,然后您只能导入您需要的组。

小例子:我们有很多数据,其中一些是用户输入,另一些是杂项初始化的结果。

module basicdata
   implicit none
   ! First the data types...
   type input_data
      integer :: a, b
   end type input_data
   type init_data
      integer :: b, c
   end type init_data

   ! ... then declare the data
   type(input_data) :: input
   type(init_data) :: init
end module basicdata

现在,如果子程序仅使用init中的数据,则只导入:

subroutine doesstuff
   use basicdata, only : init
   ...
   q = init%b
end subroutine doesstuff

这绝对不是一个普遍适用的解决方案,你从派生类型语法中获得了一些额外的冗长,然后如果你的模块不是上面的basicdata排序,它当然几乎没有帮助,而是更多的{ {1}}品种。无论如何,我已经幸运地获得了更容易进入大脑的代码。

答案 3 :(得分:3)

USE的主要优点仅在于它避免使用我不需要的东西来污染我的全局命名空间。

答案 4 :(得分:1)

同意之前给出的大多数答案,use ..., only: ...是要走的路,在有意义的时候使用类型,尽可能地应用python thinking。另一个建议是在导入的模块中使用适当的命名约定,以及private / public语句。

例如,netcdf库使用nf90_<some name>,这限制了导入方的名称空间污染。

use netcdf  ! imported names are prefixed with "nf90_"

nf90_open(...)
nf90_create(...)
nf90_get_var(...)
nf90_close(...)

同样,此库的ncio包装使用nc_<some name>nc_readnc_write ...)。

重要的是,对于use: ..., only: ...不太相关的设计,您可以通过在标题中设置适当的private / public属性来更好地控制导入模块的命名空间因此,快速浏览一下就足以让读者评估出哪种“污染”水平。他们正面临着。这基本上与use ..., only: ...相同,但在导入的模块端 - 因此只能写入一次,而不是每次导入时。)

还有一件事:就面向对象和python而言,我认为不同的是fortran并不真正鼓励类型绑定程序,部分原因是它是一个相对较新的标准(例如与工具的数量,而不是理性的,它只是不寻常的),因为它打破了方便的行为,如无过程的派生类型副本(type(mytype) :: t1, t2t2 = t1)。这意味着您经常需要导入类型和所有可能的类型绑定过程,而不仅仅是类。与python相比,仅此一点就使得fortran代码更加冗长,而像前缀命名约定这样的实用解决方案可能会派上用场。

国际海事组织,最重要的是:根据python的教导,为那些将要阅读它的人(包括你以后的自己)选择你的编码风格。最好的是每次导入时更详细use ..., only: ...,但在某些情况下,会有一个简单的命名约定(如果你足够纪律......)。

答案 5 :(得分:1)

是的,请使用use module, only: ...。对于拥有多个程序员的大型代码库,它可以让每个人都更容易理解代码(或者只使用grep)。

请不要使用include,而是使用较小的模块。 Include是源代码的文本插入,编译器在与使用模块相同的级别上未检查,请参阅:FORTRAN: Difference between INCLUDE and modulesInclude通常会使人和计算机都难以使用代码,这意味着它不应该被使用。防爆。来自mpi-forum:&#34;强烈建议不要使用mpif.h包含文件,并且可能会在将来的MPI版本中弃用。&#34; (http://mpi-forum.org/docs/mpi-3.1/mpi31-report/node411.htm)。

答案 6 :(得分:0)

我知道我参加聚会的时间有点晚了,但是如果你只是在一组常量之后并且不一定是计算值,你可以像C一样创建一个包含文件:

在文件中, 例如,constants.for

real, parameter :: pi = 3.14
real, parameter :: g = 6.67384e-11
...


program main
    use module1, only : func1, subroutine1, func2 
    implicit none

    include 'constants.for'
    ...
end program main

编辑删除“真实(4)”,因为有些人认为这是不好的做法。