web-dev-qa-db-fra.com

Comment utilisez-vous les données du module Fortran 90

Disons que vous avez un module Fortran 90 contenant lots de variables, fonctions et sous-programmes. Dans votre instruction USE, quelle convention suivez-vous:

  1. déclarer explicitement les variables/fonctions/sous-programmes que vous utilisez avec la syntaxe , only :, comme USE [module_name], only : variable1, variable2, ...?
  2. Insérez une couverture USE [module_name]?

D'une part, la clause only rend le code un peu plus verbeux. Cependant, cela vous oblige à vous répéter dans le code et si votre module contient lots de variables/fonctions/sous-programmes, les choses commencent à sembler indisciplinées.

Voici un exemple:

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

Mise à jour J'espère que quelqu'un dit quelque chose comme "Fortran? Il suffit de le recoder en C #!" pour que je puisse voter contre vous.


Mise à jour

J'aime réponse de Tim Whitcomb , qui compare le USE modulename De Fortran avec le from modulename import * De Python. Un sujet qui a déjà été sur Stack Overflow:

  • "module d'importation" ou "à partir de l'importation de module"

    • Dans une réponse , Mark Roddy a mentionné:

      n'utilisez pas 'from module import *'. Pour tout grand ensemble de code raisonnable, si vous "importez *", vous le cimenterez probablement dans le module, impossible à supprimer. En effet, il est difficile de déterminer quels éléments utilisés dans le code proviennent du `` module '', ce qui en fait un point où vous pensez que vous n'utilisez plus l'importation, mais il est extrêmement difficile d'être sûr.

  • Quelles sont les bonnes règles de base pour python importe?

    • réponse de dbr contient

      ne pas faire à partir de x import * - cela rend votre code très difficile à comprendre, car vous ne pouvez pas facilement voir d'où vient une méthode (de x import *; de y import *; my_func () - où est défini mon_func?)

Donc, je penche vers un consensus pour énoncer explicitement tous les éléments que j'utilise dans un module via

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

Et comme Stefano Borini mentionne ,

[si] vous avez un module si grand que vous vous sentez obligé d'ajouter UNIQUEMENT, cela signifie que votre module est trop gros. Sépare le.

37
Pete

C'est une question d'équilibre.

Si vous n'utilisez que quelques trucs du module, il est logique si vous ajoutez UNIQUEMENT, de spécifier clairement ce que vous utilisez.

Si vous utilisez beaucoup de choses à partir du module, spécifier UNIQUEMENT sera suivi de beaucoup de choses, donc cela a moins de sens. Vous choisissez essentiellement ce que vous utilisez, mais le fait est que vous dépendez de ce module dans son ensemble.

Cependant, à la fin, la meilleure philosophie est celle-ci: si vous êtes préoccupé par la pollution de l'espace de noms et que vous avez un module si grand que vous vous sentez obligé d'ajouter UNIQUEMENT, cela signifie que votre module est trop grand. Sépare le.

Mise à jour: Fortran? il suffit de le recoder en python;)

17
Stefano Borini

Je faisais juste use modulename - puis, au fur et à mesure que mon application grandissait, je trouvais de plus en plus difficile de trouver la source des fonctions (sans passer à grep) - certains des autres codes flottant dans le bureau utilisent toujours un sous-programme par fichier, qui a son propre ensemble de problèmes, mais il est beaucoup plus facile d'utiliser un éditeur de texte pour parcourir le code et trouver rapidement ce dont vous avez besoin.

Après avoir vécu cela, je suis devenu un converti en utilisant use...only chaque fois que possible. J'ai également commencé à prendre Python et à le voir de la même manière que from modulename import *. Il y a beaucoup de grandes choses que les modules vous offrent, mais je préfère garder mon espace de noms global étroitement contrôlé.

25
Tim Whitcomb

Ne répond pas exactement à la question ici, jetant simplement une autre solution que j'ai trouvée utile dans certaines circonstances, si pour une raison quelconque vous ne voulez pas diviser votre module et commencer à obtenir des conflits d'espace de noms. Vous pouvez utiliser des types dérivés pour stocker plusieurs espaces de noms dans un module.

S'il existe un regroupement logique des variables, vous pouvez créer votre propre type dérivé pour chaque groupe, stocker une instance de ce type dans le module, puis vous pouvez importer uniquement le groupe dont vous avez besoin.

Petit exemple: nous avons beaucoup de données dont certaines sont entrées par l'utilisateur et d'autres qui sont le résultat d'initialisations diverses.

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

Maintenant, si un sous-programme utilise uniquement des données de init, vous importez juste cela:

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

Ce n'est certainement pas une solution universellement applicable, vous obtenez un peu de verbosité supplémentaire à partir de la syntaxe de type dérivée et cela ne servira bien sûr à rien si votre module n'est pas le type basicdata ci-dessus, mais plutôt un allthestuffivebeenmeaningtosortoutvariety. Quoi qu'il en soit, j'ai eu de la chance d'obtenir un code qui s'intègre plus facilement dans le cerveau de cette façon.

6
TorbjornB

Le principal avantage de USE, UNIQUEMENT pour moi, c'est qu'il évite de polluer mon espace de noms global avec des éléments dont je n'ai pas besoin.

4
ire_and_curses

Oui, veuillez utiliser use module, only: .... Pour les grandes bases de code avec plusieurs programmeurs, cela rend le code plus facile à suivre par tout le monde (ou utilisez simplement grep).

Veuillez ne pas utiliser include, utilisez plutôt un module plus petit pour cela. Inclure est un insert de texte du code source qui n'est pas vérifié par le compilateur au même niveau que le module d'utilisation, voir: FORTRAN: Différence entre INCLUDE et modules . Include rend généralement plus difficile pour les humains et l'ordinateur d'utiliser le code, ce qui signifie qu'il ne doit pas être utilisé. Ex. de mpi-forum: "L'utilisation du fichier d'inclusion mpif.h est fortement déconseillée et pourrait être déconseillée dans une future version de MPI." ( http://mpi-forum.org/docs/mpi-3.1/mpi31-report/node411.htm ).

1
Knut Gjerden

D'accord avec la plupart des réponses précédemment données, use ..., only: ... Est la voie à suivre, utilisez des types quand cela a du sens, appliquez pensée python autant que possible. Une autre suggestion consiste à utiliser les conventions de dénomination appropriées dans votre module importé, ainsi que les instructions private/public.

Par exemple, la bibliothèque netcdf utilise nf90_<some name>, Ce qui limite la pollution de l'espace de noms du côté de l'importateur.

use netcdf  ! imported names are prefixed with "nf90_"

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

de même, le wrapper ncio de cette bibliothèque utilise nc_<some name> (nc_read, nc_write ...).

Surtout, avec de telles conceptions où use: ..., only: ... Est rendu moins pertinent, vous feriez mieux de contrôler l'espace de noms du module importé en définissant les attributs private/public appropriés dans l'en-tête, donc qu'un simple coup d'œil suffira aux lecteurs pour évaluer le niveau de "pollution" auquel ils sont confrontés. C'est fondamentalement la même chose que use ..., only: ..., Mais du côté du module importé - donc à écrire une seule fois, pas à chaque importation).

Une dernière chose: en ce qui concerne l'orientation objet et python sont concernés, une différence à mon avis est que fortran n'encourage pas vraiment les procédures liées au type, en partie parce que c'est une norme relativement nouvelle (par exemple non compatible avec un certain nombre d'outils, et moins rationnellement, c'est tout simplement inhabituel) et parce qu'il casse un comportement pratique tel que la copie de type dérivée sans procédure (type(mytype) :: t1, t2 et t2 = t1). Cela signifie que vous devez souvent importer le type et toutes les procédures liées au type, au lieu de simplement la classe. Cela seul rend le code fortran plus verbeux par rapport à python, et des solutions pratiques comme une convention de dénomination de préfixe peuvent être utiles.

OMI, la ligne de fond est la suivante: choisissez votre style de codage pour les personnes qui le liront (cela inclut votre moi ultérieur), comme enseigné par python. Le meilleur est le use ..., only: ... Le plus verbeux à chaque importation, mais dans certains cas, une simple convention de dénomination le fera (si vous êtes suffisamment discipliné ...).

1
Mahé

Je sais que je suis un peu en retard pour la fête, mais si vous ne recherchez qu'un ensemble de constantes et pas nécessairement des valeurs calculées, vous pouvez faire comme C et créer un fichier include:

à l'intérieur d'un fichier, par exemple, 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

Modifié pour supprimer "real (4)" car certains pensent que c'est une mauvaise pratique.

0
Forrest