compilation - Fortran: interfaz explícita
explicit-interface (2)
Soy muy nuevo en Fortran, y para mi investigación necesito hacer funcionar un monstruo de modelo, así que estoy aprendiendo a medida que avanzo. Entonces lo siento si hago una pregunta "estúpida". Estoy intentando compilar (Mac OSX, desde la línea de comandos) y ya he logrado resolver algunas cosas, pero ahora me he encontrado con algo que no estoy seguro de cómo solucionarlo. Creo que tengo la idea detrás del error, pero de nuevo, no estoy seguro de cómo solucionarlo.
El modelo es enorme, por lo que solo publicaré las secciones de código que considero relevantes (aunque podría estar equivocado). Tengo un archivo con varias subrutinas, que comienza con:
!==========================================================================================!
! This subroutine simply updates the budget variables. !
!------------------------------------------------------------------------------------------!
subroutine update_budget(csite,lsl,ipaa,ipaz)
use ed_state_vars, only : sitetype ! ! structure
implicit none
!----- Arguments -----------------------------------------------------------------------!
type(sitetype) , target :: csite
integer , intent(in) :: lsl
integer , intent(in) :: ipaa
integer , intent(in) :: ipaz
!----- Local variables. ----------------------------------------------------------------!
integer :: ipa
!----- External functions. -------------------------------------------------------------!
real , external :: compute_water_storage
real , external :: compute_energy_storage
real , external :: compute_co2_storage
!---------------------------------------------------------------------------------------!
do ipa=ipaa,ipaz
!------------------------------------------------------------------------------------!
! Computing the storage terms for CO2, energy, and water budgets. !
!------------------------------------------------------------------------------------!
csite%co2budget_initialstorage(ipa) = compute_co2_storage(csite,ipa)
csite%wbudget_initialstorage(ipa) = compute_water_storage(csite,lsl,ipa)
csite%ebudget_initialstorage(ipa) = compute_energy_storage(csite,lsl,ipa)
end do
return
end subroutine update_budget
!==========================================================================================!
!==========================================================================================!
Recibo mensajes de error a lo largo de las líneas de
budget_utils.f90: 20.54:
real, externo :: compute_co2_storage 1
Error: El argumento ficticio ''csite'' del procedimiento ''compute_co2_storage'' en (1) tiene un atributo que requiere una interfaz explícita para este procedimiento
(Tengo un montón de ellos, pero básicamente son todos iguales). Ahora, mirando ed_state_vars.f90 (que es "usado" en la subrutina), encuentro
!============================================================================!
!============================================================================!
!---------------------------------------------------------------------------!
! Site type:
! The following are the patch level arrays that populate the current site.
!---------------------------------------------------------------------------!
type sitetype
integer :: npatches
! The global index of the first cohort in all patches
integer,pointer,dimension(:) :: paco_id
! The number of cohorts in each patch
integer,pointer,dimension(:) :: paco_n
! Global index of the first patch in this vector, across all patches
! on the grid
integer :: paglob_id
! The patches containing the cohort arrays
type(patchtype),pointer,dimension(:) :: patch
Etc, etc. - esto va uno por otras 500 líneas más o menos. Entonces, para llegar al punto, parece que la subrutina original necesita una interfaz explícita para sus procedimientos a fin de poder usar el argumento (ficticio) csite. Una vez más, soy muy nuevo con Fortran, pero realmente intento comprender cómo "piensa". He estado buscando lo que significa tener una interfaz explícita, cuándo (¡y cómo!) Usarla, etc. Pero no puedo entender cómo se aplica en mi caso. ¿Debo tal vez usar un compilador diferente (Intel?). ¿Algún consejo?
Editar: por lo tanto, csite
se declara como un target
en todos los procedimientos y, a partir del type(site type)
declaración type(site type)
contiene un conjunto completo de pointer
, tal como se especifica en sitetype
. Pero el tipo de sitetype
se use
correctamente d desde otro módulo ( ed_state_vars.f90
) en todos los procedimientos. Entonces, todavía estoy confundido por qué me da el error de interfaz explícito?
Me encontré con los mismos problemas que encontré mientras intentaba instalar ED2 en mi mac 10.9. Lo arreglé incluyendo todas las subrutinas en ese archivo en un módulo, es decir:
module mymodule
contains
subroutine update_budget(csite,lsl,ipaa,ipaz)
other subroutines ecc.
end module mymodule
Lo mismo tenía que hacerse con unos 10 o 15 archivos más en el paquete. He compilado todos los archivos y producido los archivos de objetos correspondientes, pero ahora recibo errores sobre símbolos indefinidos. Sin embargo, sospecho que estos son independientes de las modificaciones, así que si alguien tiene la paciencia, esta podría ser una forma de resolver al menos el problema de la interfaz.
"interfaz explícita" significa que la interfaz del procedimiento (subrutina o función) se declara al compilador. Esto le permite al compilador verificar la consistencia de los argumentos entre las llamadas al procedimiento y el procedimiento real. Esto puede encontrar muchos errores de programador. Puede hacerlo escribiendo la interfaz con una declaración de interface
, pero hay un método mucho más sencillo: colocar el procedimiento en un módulo y use
ese módulo desde cualquier otra entidad que lo llame, desde el programa principal o desde cualquier otro procedimiento que no sea el mismo en el módulo Pero no use
un procedimiento de otro procedimiento en el mismo módulo: se conocen automáticamente entre sí.
La colocación de un procedimiento en un módulo hace que su interfaz sea conocida por el compilador y esté disponible para la verificación cruzada cuando se use
. Esto es más fácil y menos propenso a errores que escribir una interfaz. Con una interfaz, debe duplicar la lista de argumentos del procedimiento. Luego, si revisas el procedimiento, también tienes que revisar las llamadas (¡por supuesto!), Pero también la interfaz.
Se requiere una interfaz explícita (declaración o módulo de interface
) cuando utiliza argumentos "avanzados". De lo contrario, el compilador no sabe para generar la llamada correcta
Si tiene un procedimiento que se use
, no debe describirlo con external
. Hay muy pocos usos de external
en Fortran moderno; por lo tanto, elimine los atributos external
, ponga todos sus procedimientos en un módulo y úselos.