Come si utilizzano i dati del modulo Fortran 90
-
11-09-2019 - |
Domanda
Supponiamo che tu abbia un modulo Fortran 90 contenente molti di variabili, funzioni e subroutine.Nel tuo USE
dichiarazione, quale convenzione segui:
- dichiara esplicitamente quali variabili/funzioni/subroutine stai utilizzando con
, only :
sintassi, come ad esUSE [module_name], only : variable1, variable2, ...
? - Inserisci una coperta
USE [module_name]
?
Da un lato, il only
La clausola rende il codice un po' più dettagliato.Tuttavia, ti costringe a ripeterti nel codice e se il tuo modulo contiene molti di variabili/funzioni/subroutine, le cose cominciano a sembrare indisciplinate.
Ecco un esempio:
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
AggiornamentoSperiamo che qualcuno dica qualcosa del genere "Fortran?Basta ricodificarlo in C#!" quindi posso votarti in basso.
Aggiornamento
mi piace La risposta di Tim Whitcomb, che confronta quello di Fortran USE modulename
con Python from modulename import *
.Un argomento già presente su Stack Overflow:
"importa modulo" o "da modulo importa"
- In una risposta, Mark Roddy ha menzionato:
non utilizzare 'from module import *'.Per qualsiasi ampio set di codice ragionevole, se "importa *" probabilmente lo cementa nel modulo, incapace di essere rimosso.Questo perché è difficile determinare quali elementi usati nel codice provengono dal "modulo", rendendo a est per arrivare al punto in cui pensi di non usare più l'importazione ma è estremamente difficile essere sicuri.
- In una risposta, Mark Roddy ha menzionato:
Quali sono le buone regole pratiche per le importazioni di Python?
- la risposta di dbr contiene
Non fare da X import * - Rende il tuo codice molto difficile da capire, poiché non puoi vedere facilmente da dove proviene un metodo (da X import *;da y import *;my_func () - dove viene definito my_func?)
- la risposta di dbr contiene
Quindi, sono propenso a un consenso nel dichiarare esplicitamente tutti gli elementi che sto utilizzando in un modulo tramite
USE modulename, only : var1, var2, ...
E come Stefano Borini cita,
Se] hai un modulo così grande che ti senti costretto ad aggiungere solo, significa che il tuo modulo è troppo grande.Dividilo.
Soluzione
E 'una questione di equilibrio.
Se si utilizza solo un paio di cose dal modulo, ha senso se si aggiunge solo, per specificare in modo chiaro ciò che si sta utilizzando.
Se si utilizza un sacco di cose dal modulo, specificando solo sarà seguita da un sacco di roba, quindi ha meno senso. Tu sei fondamentalmente cherry-picking quello che si utilizza, ma il fatto vero è che siete dipendenti da quel modulo nel suo complesso.
Tuttavia, alla fine il migliore filosofia è questa: se siete preoccupati per l'inquinamento dello spazio dei nomi, e si dispone di un modulo così grande che si sente in dovere di aggiungere solo, significa che il modulo è troppo grande. Split.
Aggiornamento: Fortran? solo ricodificare in python;)
Altri suggerimenti
ho usato per fare proprio use modulename
- allora, come la mia domanda è cresciuta, l'ho trovato sempre più difficile da trovare la fonte di funzioni (senza girare a grep) - alcuni dei altro codice che galleggia intorno all'ufficio utilizza ancora uno -subroutine-per-file, che ha una propria serie di problemi, ma rende molto più facile da usare un editor di testo per passare attraverso il codice e rapidamente rintracciare quello che ti serve.
Dopo aver sperimentato questo, sono diventato un convertito al utilizzando use
... only
quando possibile. Ho anche iniziato a raccogliere Python, e vederlo allo stesso modo di from modulename import *
. Ci sono un sacco di grandi cose che ti danno i moduli, ma preferisco mantenere il mio namespace globale strettamente controllato.
Non rispondo esattamente alla domanda qui, sto solo inserendo un'altra soluzione che ho trovato utile in alcune circostanze, se per qualsiasi motivo non vuoi dividere il tuo modulo e iniziare a ricevere conflitti nello spazio dei nomi.È possibile utilizzare tipi derivati per archiviare diversi spazi dei nomi in un modulo.
Se esiste un raggruppamento logico delle variabili, puoi creare il tuo tipo derivato per ciascun gruppo, memorizzare un'istanza di questo tipo nel modulo e quindi puoi importare solo il gruppo di cui hai bisogno.
Piccolo esempio:Abbiamo molti dati, alcuni dei quali sono input dell'utente e altri sono il risultato di inizializzazioni varie.
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
Ora, se una subroutine utilizza solo i dati da init
, importi proprio questo:
subroutine doesstuff
use basicdata, only : init
...
q = init%b
end subroutine doesstuff
Questa non è sicuramente una soluzione universalmente applicabile, ottieni un po' di verbosità extra dalla sintassi del tipo derivato e quindi ovviamente sarà di scarso aiuto se il tuo modulo non è quello basicdata
ordina sopra, ma invece più di a allthestuffivebeenmeaningtosortout
varietà.Ad ogni modo, ho avuto un po' di fortuna nell'ottenere codice che si adatta più facilmente al cervello in questo modo.
Il principale vantaggio di utilizzo, solo per me è che evita inquinare il mio namespace globale con roba non ho bisogno.
Concordo con la maggior parte delle risposte fornite in precedenza, use ..., only: ...
è la strada da percorrere, usa i tipi quando ha senso, applica pensiero pitone per quanto possibile.Un altro suggerimento è quello di utilizzare convenzioni di denominazione appropriate nel modulo importato, insieme a private
/ public
dichiarazioni.
Ad esempio, il netcdf
usi della biblioteca nf90_<some name>
, che limita l'inquinamento dello spazio dei nomi da parte dell'importatore.
use netcdf ! imported names are prefixed with "nf90_"
nf90_open(...)
nf90_create(...)
nf90_get_var(...)
nf90_close(...)
allo stesso modo, il nci wrapper per questa libreria utilizza nc_<some name>
(nc_read
, nc_write
...).
È importante sottolineare che con tali progetti dove use: ..., only: ...
viene reso meno rilevante, è meglio controllare lo spazio dei nomi del modulo importato impostando il file appropriate private
/ public
attributi nell'intestazione, così che ai lettori basterà una rapida occhiata per valutare quale livello di "inquinamento" si trovano ad affrontare.Questo è fondamentalmente lo stesso di use ..., only: ...
, ma sul lato del modulo importato - quindi da scrivere solo una volta, non ad ogni importazione).
Un'altra cosa:per quanto riguarda l'orientamento agli oggetti e Python, una differenza a mio avviso è che Fortran non incoraggia realmente le procedure legate al tipo, in parte perché è uno standard relativamente nuovo (ad es.non compatibile con una serie di strumenti e, in modo meno razionale, è semplicemente insolito) e perché interrompe comportamenti pratici come la copia di tipo derivato senza procedure (type(mytype) :: t1, t2
E t2 = t1
).Ciò significa che spesso è necessario importare il tipo e tutte le potenziali procedure legate al tipo, anziché solo la classe.Questo da solo rende il codice Fortran più dettagliato rispetto a Python e soluzioni pratiche come una convenzione di denominazione del prefisso possono tornare utili.
Secondo me, il punto è:scegli il tuo stile di codifica per le persone che lo leggeranno (questo include te stesso in seguito), come insegnato da Python.Il migliore è il più dettagliato use ..., only: ...
ad ogni importazione, ma in alcuni casi basterà una semplice convenzione di denominazione (se sei abbastanza disciplinato...).
Sì, si prega di utilizzare use module, only: ...
. Per basi di codice di grandi dimensioni con più programmatori, rende il codice più facile da seguire da tutti (o semplicemente utilizzare grep
).
Si prega di non utilizzare includono, utilizzare un modulo più piccolo per che, invece. Includi è un inserto del testo del codice sorgente, che non viene controllato dal compilatore allo stesso livello di modulo di uso, consultare: FORTRAN: Differenza tra inclusione ed i moduli . Include
generalmente rende più difficile per gli esseri umani e computer di utilizzare il codice che significa che non deve essere utilizzato. Ex. da mpi-forum: "L'uso del mpif.h file include è fortemente sconsigliato e può essere obsoleto in una futura versione di MPI." ( http://mpi-forum.org/docs/mpi -3.1 / mpi31-report / node411.htm ).
Lo so che sono un po 'in ritardo alla festa, ma se siete solo dopo una serie di costanti e non necessariamente i valori calcolati, si potrebbe fare come il C e creare un file di inclusione:
all'interno di un file, per esempio, 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
A cura di rimuovere "reale (4)", come alcuni pensano che è una cattiva pratica.