module - compilar modulos fortran
¿Cómo se utilizan los datos del módulo Fortran 90? (7)
Digamos que tiene un módulo Fortran 90 que contiene muchas variables, funciones y subrutinas. En su declaración USE
, qué convención sigue:
- declare explícitamente qué variables / funciones / subrutinas está utilizando con la sintaxis, como
USE [module_name], only : variable1, variable2, ...
? - Inserte una manta
USE [module_name]
?
Por un lado, la only
cláusula hace que el código sea un poco más detallado. Sin embargo, te obliga a repetirte en el código y si tu módulo contiene muchas variables / funciones / subrutinas, las cosas empiezan a parecer ingobernables.
Aquí hay un ejemplo:
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
Actualización: Afortunadamente, alguien dice algo como "¡Fortran! ¡Recógelo en C #!" así puedo votar por ti.
Actualizar
Me gusta la respuesta de Tim Whitcomb , que compara el nombre de USE modulename
con Python del nombre from modulename import *
. Un tema que ha estado en Desbordamiento de pila antes:
''importar módulo'' o ''desde módulo de importación''
- En una respuesta , Mark Roddy mencionó:
no use ''desde la importación del módulo *''. Para cualquier gran conjunto razonable de código, si ''importa *'' probablemente lo cementará en el módulo, sin poder ser eliminado. Esto se debe a que es difícil determinar qué elementos utilizados en el código provienen de ''módulo'', por lo que es necesario llegar al punto donde crees que ya no usas la importación, pero es extremadamente difícil estar seguro.
- En una respuesta , Mark Roddy mencionó:
¿Cuáles son las buenas reglas generales para las importaciones de Python?
- La respuesta de dbr contiene
no lo haga desde x import *: hace que su código sea muy difícil de entender, ya que no puede ver fácilmente de dónde vino un método (de x import *; from y import *; my_func () - ¿dónde se define my_func?)
- La respuesta de dbr contiene
Por lo tanto, me estoy inclinando hacia un consenso de establecer explícitamente todos los elementos que estoy usando en un módulo a través de
USE modulename, only : var1, var2, ...
Y como Stefano Borini menciona ,
[si] tiene un módulo tan grande que se siente obligado a agregar SOLAMENTE, significa que su módulo es demasiado grande. Dividirlo.
De acuerdo con la mayoría de las respuestas dadas anteriormente, use ..., only: ...
es el camino a seguir, use tipos cuando tenga sentido, aplique el pensamiento python tanto como sea posible. Otra sugerencia es utilizar convenciones de nomenclatura apropiadas en su módulo importado, junto con declaraciones private
/ public
.
Por ejemplo, la biblioteca netcdf
usa nf90_<some name>
, que limita la contaminación del espacio de nombres en el lado del importador.
use netcdf ! imported names are prefixed with "nf90_"
nf90_open(...)
nf90_create(...)
nf90_get_var(...)
nf90_close(...)
del mismo modo, el contenedor ncio de esta biblioteca usa nc_<some name>
( nc_read
, nc_write
...).
Es importante destacar que, con tales diseños donde el use: ..., only: ...
se vuelve menos relevante, es mejor que controle el espacio de nombres del módulo importado estableciendo public
atributos private
/ public
apropiados en el encabezado, de modo que un vistazo rápido a será suficiente para los lectores evaluar qué nivel de "contaminación" están enfrentando. Esto es básicamente lo mismo que use ..., only: ...
, pero en el lado del módulo importado, por lo tanto, debe escribirse una sola vez, no en cada importación.
Una cosa más: en lo que se refiere a orientación de objetos y python, una diferencia en mi opinión es que fortran realmente no fomenta los procedimientos de escritura de tipo, en parte porque es un estándar relativamente nuevo (por ejemplo, no compatible con varias herramientas). , y de manera menos racional, es simplemente inusual) y porque rompe el comportamiento práctico, como la copia de tipo derivado libre de procedimiento ( type(mytype) :: t1, t2
y t2 = t1
). Eso significa que a menudo tiene que importar el tipo y todos los posibles procedimientos de escritura de tipo, en lugar de solo la clase. Esto solo hace que el código fortran sea más detallado en comparación con Python, y las soluciones prácticas como una convención de nomenclatura de prefijo pueden ser útiles.
IMO, la conclusión es: elija su estilo de codificación para las personas que lo leerán (esto incluye su yo posterior), como lo enseña Python. Lo mejor es el use ..., only: ...
más detallado use ..., only: ...
en cada importación, pero en algunos casos una simple convención de nomenclatura lo hará (si eres lo suficientemente disciplinado ...).
Es una cuestión de equilibrio.
Si usa solo algunas cosas del módulo, tiene sentido si solo lo agrega, para especificar claramente qué está usando.
Si usa muchas cosas del módulo, especificar SÓLO irá seguido de muchas cosas, por lo que tiene menos sentido. Básicamente, estás eligiendo lo que usas, pero la verdad es que dependes de ese módulo como un todo.
Sin embargo, al final, la mejor filosofía es esta: si le preocupa la contaminación del espacio de nombres, y tiene un módulo tan grande que se siente obligado a agregar SOLAMENTE, significa que su módulo es demasiado grande. Dividirlo.
Actualización: Fortran? solo recodifícalo en python;)
La principal ventaja de USE, SÓLO para mí es que evita contaminar mi espacio de nombres global con cosas que no necesito.
No estoy respondiendo exactamente la pregunta aquí, simplemente lanzando otra solución que he encontrado útil en algunas circunstancias, si por alguna razón no quieres dividir tu módulo y comenzar a tener conflictos en el espacio de nombres. Puede usar tipos derivados para almacenar varios espacios de nombres en un módulo.
Si hay alguna agrupación lógica de las variables, puede crear su propio tipo derivado para cada grupo, almacenar una instancia de este tipo en el módulo y luego puede importar solo el grupo que necesite.
Pequeño ejemplo: tenemos muchos datos, algunos de los cuales son datos del usuario y otros son el resultado de varias inicializaciones.
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
Ahora, si una subrutina solo usa datos de init
, solo importa eso:
subroutine doesstuff
use basicdata, only : init
...
q = init%b
end subroutine doesstuff
Definitivamente no es una solución aplicable universalmente, usted obtiene algo de verbosidad extra a partir de la sintaxis del tipo derivado y entonces, por supuesto, apenas ayudará si su módulo no es el tipo basicdata
anterior, sino más bien todo lo que allthestuffivebeenmeaningtosortout
variedad. De todos modos, he tenido un poco de suerte para obtener un código que se adapte mejor al cerebro de esta manera.
Sé que llego un poco tarde a la fiesta, pero si solo buscas un conjunto de constantes y no valores calculados, puedes hacer C y crear un archivo de inclusión:
dentro de un archivo, por ejemplo, constantes.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
Editado para eliminar "real (4)" ya que algunos piensan que es una mala práctica.
Sí, use module, only: ...
Para grandes bases de código con múltiples programadores, hace que el código sea más fácil de seguir por todos (o simplemente use grep
).
No use include, use un módulo más pequeño para eso. Incluir es una inserción de texto del código fuente que el compilador no verifica en el mismo nivel que el módulo de uso, ver: FORTRAN: Diferencia entre INCLUDE y módulos . Include
generalmente hace que sea más difícil para los humanos y la computadora usar el código, lo que significa que no se debe usar. Ex. from mpi-forum: "El uso del archivo de inclusión mpif.h está muy desaconsejado y puede ser desaprobado en una versión futura de MPI". ( http://mpi-forum.org/docs/mpi-3.1/mpi31-report/node411.htm ).
Solía use modulename
; luego, a medida que crecía mi aplicación, me resultaba cada vez más difícil encontrar la fuente de las funciones (sin recurrir a grep): algunos de los otros códigos que flotan en la oficina aún usan una sola subrutina -per-file, que tiene su propio conjunto de problemas, pero hace que sea mucho más fácil usar un editor de texto para moverse a través del código y rastrear rápidamente lo que necesita.
Después de experimentar esto, me convertí en un converso al use
... only
cuando sea posible. También comencé a buscar Python, y lo veo de la misma manera que from modulename import *
. Hay muchas cosas geniales que los módulos le brindan, pero prefiero mantener mi espacio de nombres global estrictamente controlado.