pasar la matriz asignada de la subrutina al programa principal en fortran; uso o módulo? ¿interfaz?
Quiero asignar una matriz en una subrutina y luego usar esta matriz en el programa principal y pasarla a otra subrutina. En el pasado (¿F77?) El paso se podía hacer en un bloque común, pero hoy en día el procedimiento preferido parece ser utilizar un módulo. Cuando intento esto, como en el ejemplo de código, el compilador me dice
Rank mismatch in argument ‘f’ at (1) (scalar and rank-1)
Aparentemente, el programa principal piensa que 'f' es un escalar: pero leí este código para significar que lo he declarado como una matriz unidimensional, tanto dentro de la subrutina como en el programa principal. ¿Qué me estoy perdiendo?
Probé variaciones, como declarar las variables como parte del módulo, pero nada en lo que pudiera pensar hizo que la compilación estuviera libre de errores (y algunas produjeron muchos más errores ;-(). Cualquier información es muy apreciada.
module subs
contains
subroutine makef(f)
end subroutine makef
end module subs
c-----------------------------------------------------------------------
program work
use subs
implicit none
real, allocatable :: f(:)
call makef(f)
write (*,*) f
stop
end
c---------------------------------------------------------------------
subroutine makef(f)
implicit none
real, allocatable, intent(out) :: f(:)
integer :: i
integer :: is
is=10
allocate(f(-is:is))
do i=-is,is
f(i)=i
end do
return
end subroutine makef
Respuestas
Los módulos en Fortran no son como archivos de encabezado en otros lenguajes que simplemente proporcionan información sobre cosas definidas en otro lugar. Existe el concepto de "definición diferida" (submódulos) pero en este caso el módulo debe decir todo sobre la subrutina, no simplemente intentar señalar su existencia.
En el ejemplo de la pregunta, tenemos: el programa principal; un módulo subs
con procedimiento de módulo makef
; una subrutina externa makef
.
El programa principal utiliza el módulo subs
y su procedimiento makef
, por lo que en el programa principal se hace referencia makef
al procedimiento del módulo, no a la subrutina externa makef
.
La subrutina del módulo makef
tiene el argumento f
que no tiene declaraciones de declaración, por lo que es una función escalar / externa declarada implícitamente. Este es el mensaje del compilador. Úselo implicit noneen módulos, tal como está en el programa principal y en la subrutina externa aquí.
La definición completa de la subrutina debe colocarse en el módulo:
module subs
implicit none
contains
subroutine makef(f)
real, allocatable, intent(out) :: f(:)
integer :: i
integer :: is
is=10
allocate(f(-is:is))
do i=-is,is
f(i)=i
end do
end subroutine makef
end module subs
Alternativamente, si uno quiere referirse a la implementación posterior de un procedimiento externo, un bloque de interfaz puede aparecer en el módulo sin declarar la subrutina en sí. En este caso, aún será necesario especificar la interfaz completa:
module subs
implicit none
! An interface block to give an explicit interface to the external subroutine makef
interface
subroutine makef(f)
implicit none
real, allocatable, intent(out) :: f(:)
end subroutine makef
end interface
end module subs
En este caso, no prefiera el bloque de interfaz.
Solo colocó la copia de la primera y la última línea en el módulo. Eso no puede funcionar. Debe mover toda la subrutina al módulo.