如何使用 Fortran 90 模块数据

发布于 2024-07-30 13:04:14 字数 2987 浏览 8 评论 0原文

假设您有一个 Fortran 90 模块,其中包含大量变量、函数和子例程。 在 USE 语句中,您遵循以下约定:使用

  1. , only : 语法显式声明您要使用的变量/函数/子例程,例如 USE [模块名称],仅:变量1,变量2,...
  2. 插入毯子使用[模块名称]

一方面,only 子句使代码变得更加冗长。 然而,它迫使您在代码中重复自己,如果您的模块包含很多变量/函数/子例程,事情就会开始看起来不规则。

这是一个示例:

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# 重新编码!”之类的话,这样我就可以否决你的票。


更新

我喜欢蒂姆·惠特科姆的答案,它将 Fortran 的 USE modulename 与 Python 的 from modulename import * 进行比较。 Stack Overflow 上以前出现过的主题:

  • 'import module' 或 'from模块导入'

    • Mark Roddy 在回答中提到: <块引用>

      不要使用“from module import *”。 为了 任何合理的大型代码集,如果 你'导入*'你可能会 将其粘合到模块中,无法 即将被删除。 这是因为它是 很难确定使用了什么物品 代码中的内容来自“模块”, 向东行驶以到达要点 当你认为你不使用 不再进口,但它非常 很难确定。

  • Python 导入的良好经验规则是什么?< /a>

    • dbr 的回答包含 <块引用>

      不要执行 from x import * - 它会使 你的代码很难理解,因为 你无法轻易看出方法在哪里 来自(来自 x 导入 *;来自 y 进口 *; my_func() - my_func 在哪里 定义?)

因此,我倾向于通过

USE modulename, only : var1, var2, ...

And 作为 斯特凡诺·博里尼提到

[如果]你的模块太大了 觉得有必要添加ONLY,这意味着 你的模块太大了。 拆分它。

Let's say you have a Fortran 90 module containing lots of variables, functions and subroutines. In your USE statement, which convention do you follow:

  1. explicitly declare which variables/functions/subroutines you're using with the , only : syntax, such as USE [module_name], only : variable1, variable2, ...?
  2. Insert a blanket USE [module_name]?

On the one hand, the only clause makes the code a bit more verbose. However, it forces you to repeat yourself in the code and if your module contains lots of variables/functions/subroutines, things begin to look unruly.

Here's an example:

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

Update
Hopefully someone says something like "Fortran? Just recode it in C#!" so I can down vote you.


Update

I like Tim Whitcomb's answer, which compares Fortran's USE modulename with Python's from modulename import *. A topic which has been on Stack Overflow before:

  • ‘import module’ or ‘from module import’

    • In an answer, Mark Roddy mentioned:

      don't use 'from module import *'. For
      any reasonable large set of code, if
      you 'import *' your will likely be
      cementing it into the module, unable
      to be removed. This is because it is
      difficult to determine what items used
      in the code are coming from 'module',
      making it east to get to the point
      where you think you don't use the
      import anymore but its extremely
      difficult to be sure.

  • What are good rules of thumb for python imports?

    • dbr's answer contains

      don't do from x import * - it makes
      your code very hard to understand, as
      you cannot easily see where a method
      came from (from x import *; from y
      import *; my_func() - where is my_func
      defined?)

So, I'm leaning towards a consensus of explicitly stating all the items I'm using in a module via

USE modulename, only : var1, var2, ...

And as Stefano Borini mentions,

[if] you have a module so large that you
feel compelled to add ONLY, it means
that your module is too big. Split it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

再可℃爱ぅ一点好了 2024-08-06 13:04:15

我曾经只是使用 use modulename - 然后,随着我的应用程序的增长,我发现找到函数源越来越困难(不转向 grep) - 一些其他代码漂浮在Office 仍然使用每个文件一个子例程,这有其自身的一系列问题,但它使使用文本编辑器在代码中移动并快速找到您需要的内容变得更加容易。

经历过这些之后,我已经转变为尽可能使用use...only。 我也开始学习 Python,并以与 from modulename import * 相同的方式查看它。 模块为您提供了很多很棒的东西,但我更喜欢严格控制我的全局命名空间。

I used to just do use modulename - then, as my application grew, I found it more and more difficult to find the source to functions (without turning to grep) - some of the other code floating around the office still uses a one-subroutine-per-file, which has its own set of problems, but it makes it much easier to use a text editor to move through the code and quickly track down what you need.

After experiencing this, I've become a convert to using use...only whenever possible. I've also started picking up Python, and view it the same way as from modulename import *. There's a lot of great things that modules give you, but I prefer to keep my global namespace tightly controlled.

如梦初醒的夏天 2024-08-06 13:04:15

这是一个平衡问题。

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

如果您使用模块中的大量内容,则指定 ONLY 后将跟随大量内容,因此意义不大。 您基本上是在挑选您使用的内容,但事实是您依赖于该模块作为一个整体。

然而,最终最好的哲学是这样的:如果您担心名称空间污染,并且您有一个如此大的模块,以至于您不得不仅添加,则意味着您的模块太大了。 分开它。

更新:Fortran? 只需用 python 重新编码即可;)

It's a matter of balance.

If you use only a few stuff from the module, it makes sense if you add ONLY, to clearly specify what you are using.

If you use a lot of stuff from the module, specifying ONLY will be followed by a lot of stuff, so it makes less sense. You are basically cherry-picking what you use, but the true fact is that you are dependent on that module as a whole.

However, in the end the best philosophy is this one: if you are concerned about namespace pollution, and you have a module so large that you feel compelled to add ONLY, it means that your module is too big. Split it.

Update: Fortran? just recode it in python ;)

意中人 2024-08-06 13:04:15

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

如果变量有某种逻辑分组,您可以为每个组创建您自己的派生类型,在模块中存储该类型的实例,然后您可以仅导入您恰好需要的组。

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

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 类型,而是更多的 allthestuffivebeenmeaningtosortout 类型。 不管怎样,我很幸运地通过这种方式获得了更容易进入大脑的代码。

Not exactly answering the question here, just throwing in another solution that I have found useful in some circumstances, if for whatever reason you don't want to split your module and start to get namespace clashes. You can use derived types to store several namespaces in one module.

If there is some logical grouping of the variables, you can create your own derived type for each group, store an instance of this type in the module and then you can import just the group that you happen to need.

Small example: We have a lot of data some of which is user input and some that is the result of miscellaneous initializations.

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

Now if a subroutine only uses data from init, you import just that:

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

This is definitely not a universally applicable solution, you get some extra verbosity from the derived type syntax and then it will of course barely help if your module is not the basicdata sort above, but instead more of a allthestuffivebeenmeaningtosortoutvariety. Anyway, I have had some luck in getting code that fits easier into the brain this way.

梦里梦着梦中梦 2024-08-06 13:04:15

USE, ONLY 对我来说的主要优点是它避免了我不需要的东西污染我的全局命名空间。

The main advantage of USE, ONLY for me is that it avoids polluting my global namespace with stuff I don't need.

梦途 2024-08-06 13:04:15

同意之前给出的大多数答案, use ..., only: ... 是正确的方法,在有意义时使用类型,应用 Python 思维 尽可能多。 另一个建议是在导入的模块中使用适当的命名约定以及 private / public 语句。

例如,netcdf 库使用 nf90_,这限制了导入方的命名空间污染。

use netcdf  ! imported names are prefixed with "nf90_"

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

同样,此库的 ncio 包装器使用 nc_nc_readnc_write...)。

重要的是,对于这样的设计,其中 use: ..., only: ... 的相关性较低,您最好通过设置适当的 private / 标头中的 public 属性,这样读者快速浏览一下就足以评估他们所面临的“污染”程度。 这与 use ..., only: ... 基本相同,但在导入的模块方面 - 因此仅写入一次,而不是在每次导入时写入)。

还有一件事:就面向对象和 python 而言,我认为的一个区别是 fortran 并不真正鼓励类型绑定过程,部分原因是它是一个相对较新的标准(例如与许多工具不兼容) ,而且不太合理,它只是不寻常),并且因为它破坏了方便的行为,例如无过程派生类型复制(type(mytype) :: t1, t2t2 = t1代码>)。 这意味着您通常必须导入类型和所有可能的类型绑定过程,而不仅仅是类。 仅此一点就使得 Fortran 代码比 Python 更冗长,并且诸如前缀命名约定之类的实用解决方案可能会派上用场。

IMO,底线是:为将要阅读它的人(这包括你后来的自己)选择你的编码风格,正如 python 所教的那样。 最好的是在每次导入时使用更详细的 use ..., only: ... ,但在某些情况下,一个简单的命名约定就可以做到这一点(如果你有足够的纪律......)。

Agreed with most answers previously given, use ..., only: ... is the way to go, use types when it makes sense, apply python thinking as much as possible. Another suggestion is to use appropriate naming conventions in your imported module, along with private / public statements.

For instance, the netcdf library uses nf90_<some name>, which limits the namespace pollution on the importer side.

use netcdf  ! imported names are prefixed with "nf90_"

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

similarly, the ncio wrapper to this library uses nc_<some name> (nc_read, nc_write...).

Importantly, with such designs where use: ..., only: ... is made less relevant, you'd better control the namespace of the imported module by setting appropriate private / public attributes in the header, so that a quick look at it will be sufficient for readers to assess which level of "pollution" they are facing. This is basically the same as use ..., only: ..., but on the imported module side - thus to be written only once, not at each import).

One more thing: as far as object-orientation and python are concerned, a difference in my view is that fortran does not really encourage type-bound procedures, in part because it is a relatively new standard (e.g. not compatible with a number of tools, and less rationally, it is just unusual) and because it breaks handy behavior such as procedure-free derived type copy (type(mytype) :: t1, t2 and t2 = t1). That means you often have to import the type and all would-be type-bound procedures, instead of just the class. This alone makes fortran code more verbose compared to python, and practical solutions like a prefix naming convention may come in handy.

IMO, the bottom line is: choose your coding style for people who will read it (this includes your later self), as taught by python. The best is the more verbose use ..., only: ... at each import, but in some cases a simple naming convention will do it (if you are disciplined enough...).

把时间冻结 2024-08-06 13:04:15

是的,请使用使用模块,仅:...。 对于具有多个程序员的大型代码库,它使每个人都更容易理解代码(或者仅使用 grep)。

请不要使用 include,而是使用较小的模块。 Include 是源代码的文本插入,编译器不会在与 use 模块相同的级别上对其进行检查,请参阅:FORTRAN:INCLUDE 和模块之间的区别包含通常会使人和计算机都更难使用该代码,这意味着不应该使用它。 前任。 来自 mpi-forum:“强烈建议不要使用 mpif.h 包含文件,并且可能会在 MPI 的未来版本中弃用。” (http://mpi-forum.org/docs/mpi -3.1/mpi31-report/node411.htm)。

Yes, please use use module, only: .... For large code bases with multiple programmers, it makes the code easier to follow by everyone (or just use grep).

Please do not use include, use a smaller module for that instead. Include is a text insert of source code which is not checked by the compiler at the same level as use module, see: FORTRAN: Difference between INCLUDE and modules. Include generally makes it harder for both humans and computer to use the code which means it should not be used. Ex. from mpi-forum: "The use of the mpif.h include file is strongly discouraged and may be deprecated in a future version of MPI." (http://mpi-forum.org/docs/mpi-3.1/mpi31-report/node411.htm).

如梦 2024-08-06 13:04:15

我知道我来晚了一点,但如果您只需要一组常量而不一定是计算值,您可以像 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

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

I know I'm a little late to the party, but if you're only after a set of constants and not necessarily computed values, you could do like C and create an include file:

inside a file,
e.g., 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

Edited to remove "real(4)" as some think it is bad practice.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文