web-dev-qa-db-ja.com

Fortran 90モジュールデータの使用方法

lotsの変数、関数、サブルーチンを含むFortran 90モジュールがあるとします。 USEステートメントで、次の規則に従います。

  1. , only :などのUSE [module_name], only : variable1, variable2, ...構文を使用して、使用している変数/関数/サブルーチンを明示的に宣言しますか?
  2. ブランケットを挿入USE [module_name]

一方で、only句はコードをもう少し冗長にします。ただし、コード内で自分自身を繰り返す必要があり、モジュールにlotsの変数/関数/サブルーチンが含まれていると、物事が見苦しくなり始めます。

次に例を示します。

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誰かが "Fortran?C#でコーディングし直せ!"投票してください。


更新

Tim Whitcombの答え が好きです。FortranのUSE modulenameとPythonのfrom modulename import *を比較します。以前にStack Overflowにあったトピック:

  • 「モジュールのインポート」または「モジュールのインポートから」

    • 回答 、マーク・ロディは次のように述べました:

      「from module import *」を使用しないでください。妥当な大規模なコードセットの場合、「*インポート」すると、モジュールにセメントで固定され、削除できなくなります。これは、コードで使用されているアイテムが「モジュール」からのものであるかどうかを判断するのが難しく、インポートをもう使用しないと思うポイントに到達するのが東になっているためです。

  • python imports? の良い経験則は何ですか?)==

    • dbr's answer contains

      x import *からしないでください-メソッドがどこから来たのか簡単に見ることができないため、コードを理解するのが非常に難しくなります(x import *; from y import *; my_func()-my_funcはどこで定義されていますか?)

だから、私はモジュールで使用しているすべてのアイテムを明示的に述べることのコンセンサスに傾いています

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

そして ステファノボリーニが言及 のように、

[もし]モジュールが大きすぎて追加のみを強いられている場合、それはモジュールが大きすぎることを意味します。それを分割します。

35
Pete

それはバランスの問題です。

モジュールからいくつかのものだけを使用する場合は、使用しているものを明確に指定するために、ONLYを追加すれば意味があります。

モジュールから多くのものを使用する場合、ONLYを指定すると多くのものが続くため、あまり意味がありません。あなたは基本的にあなたが使用するものをピッキングしていますが、本当の事実はあなたがそのモジュール全体に依存しているということです。

ただし、最終的には、これが最良の哲学です。名前空間の汚染を心配していて、追加する必要があるほど大きなモジュールがある場合は、モジュールが大きすぎることを意味します。それを分割します。

更新:Fortran? python;)でコーディングし直すだけです

16
Stefano Borini

以前はuse modulenameを実行していました-その後、アプリケーションが成長するにつれて、関数のソースを見つけるのがますます難しくなりました(grepを使用せずに)ファイルごとに1つのサブルーチンがあります。これには独自の問題がありますが、テキストエディターを使用してコード内を移動し、必要なものをすばやく追跡することがはるかに簡単になります。

これを経験した後、可能な限りuse...onlyを使用するようになりました。また、Pythonの取得を開始し、from modulename import *と同じ方法で表示します。モジュールが提供する素晴らしい機能はたくさんありますが、私はグローバルな名前空間を厳しく管理したいのです。

25
Tim Whitcomb

ここでの質問に正確に答えているわけではなく、何らかの理由でモジュールを分割して名前空間の衝突を開始したくない場合は、いくつかの状況で有用であることがわかった別のソリューションを投げます。派生型を使用して、1つのモジュールに複数の名前空間を格納できます。

変数の論理的なグループ化がある場合、各グループに独自の派生型を作成し、この型のインスタンスをモジュールに保存して、必要なグループのみをインポートできます。

小さな例:多くのデータがあり、その一部はユーザー入力であり、その他のデータはさまざまな初期化の結果です。

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ソートではなく、むしろallthestuffivebeenmeaningtosortoutvariety。とにかく、この方法で脳に簡単に収まるコードを手に入れることができました。

6
TorbjornB

USEの主な利点は、私だけが、必要のないものでグローバルネームスペースを汚染しないことです。

4
ire_and_curses

はい、use module, only: ...を使用してください。複数のプログラマーがいる大規模なコードベースの場合、誰でも簡単にコードをフォローできます(またはgrepを使用します)。

インクルードを使用しないでください。代わりに小さなモジュールを使用してください。 includeは、useモジュールと同じレベルでコンパイラーによってチェックされないソースコードのテキスト挿入です。 FORTRAN:INCLUDEとモジュールの違い を参照してください。 Includeは一般に、人間とコンピューターの両方がコードを使用することを難しくします。つまり、使用すべきではありません。例from mpi-forum:「mpif.hインクルードファイルの使用は強く推奨されておらず、MPIの将来のバージョンでは非推奨になる可能性があります。」 ( http://mpi-forum.org/docs/mpi-3.1/mpi31-report/node411.htm )。

1
Knut Gjerden

以前に与えられたほとんどの答えに同意し、_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_read_、_nc_write_...)を使用します。

重要なのは、_use: ..., only: ..._の関連性が低くなるような設計では、ヘッダーに適切なprivate/public属性を設定することにより、インポートされたモジュールの名前空間を制御することです。読者がどのレベルの「汚染」に直面しているかを評価するには、それを簡単に調べるだけで十分です。これは基本的に_use ..., only: ..._と同じですが、インポートされたモジュール側にあります-したがって、インポートごとにではなく、一度だけ書き込まれます)。

もう1つ:オブジェクト指向とpythonに関する限り、私の見解の違いは、Fortranは比較的新しい標準であるため、タイプバインドされたプロシージャを実際に奨励していないということです(たとえば、いくつかのツールと互換性がなく、合理的ではないが、それは異常なことです)、また、プロシージャフリーの派生型コピー(type(mytype) :: t1, t2および_t2 = t1_)などの便利な動作を壊します。これは、クラスだけでなく、タイプとすべてのタイプバインドプロシージャをインポートする必要があることを意味します。これだけでも、Fortranコードはpythonよりも冗長になり、プレフィックスの命名規則などの実用的なソリューションが役立ちます。

IMO、一番下の行は、Pythonで教えられているように、それを読む人(これには後の自分を含む)のコーディングスタイルを選択することです。最良の方法は、各インポートでより詳細な_use ..., only: ..._ですが、場合によっては、単純な命名規則がそれを行います(十分な規律があれば...)。

1
Mahé

私はパーティーに少し遅れていることを知っていますが、定数と必ずしも計算された値のセットの後だけであれば、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)」を削除するように編集され、一部の人は悪い習慣だと考えています。

0
Forrest